OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3375|回复: 3

fatfs中cc936里面的两个数组

[复制链接]

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2097
金钱
2097
注册时间
2014-3-7
在线时间
491 小时
发表于 2018-9-7 09:58:54 | 显示全部楼层 |阅读模式
本帖最后由 ssssssssssss 于 2018-9-7 10:08 编辑

fatfs中cc936里面的两个数组const WCHAR uni2oem[] = {};const WCHAR oem2uni[] = {};教程里面说这两个是unicode和gbk互转的编码表,既然是互转为什么要两个数组,一个不就行了吗?看注释的话是OEMCP,有点不懂了,最后附上转换函数大神求指点[mw_shl_code=c,true]WCHAR ff_convert (        /* Converted code, 0 means conversion error */
        WCHAR        chr,        /* Character code to be converted */
        UINT        dir                /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
        const WCHAR *p;
        WCHAR c;
        int i, n, li, hi;


        if (chr < 0x80)
        {        /* ASCII */
                c = chr;
        }else
        {
                if (dir)
                {                /* OEMCP to unicode */
                        p = oem2uni;
                        hi = sizeof oem2uni / 4 - 1;
                } else
                {                /* Unicode to OEMCP */
                        p = uni2oem;
                        hi = sizeof uni2oem / 4 - 1;
                }
                li = 0;
                for (n = 16; n; n--)
                {
                        i = li + (hi - li) / 2;
                        if (chr == p[i * 2]) break;
                        if (chr > p[i * 2])
                        {
                                li = i;
                        }
                        else
                        {
                                hi = i;
                        }
                }
                c = n ? p[i * 2 + 1] : 0;
        }

        return c;
}



WCHAR ff_wtoupper (        /* Upper converted character */
        WCHAR chr                /* Input character */
)
{
        static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 };
        static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 };
        int i;


        for (i = 0; tbl_lower && chr != tbl_lower; i++) ;

        return tbl_lower ? tbl_upper : chr;
}
[/mw_shl_code]
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2018-8-3
在线时间
3 小时
发表于 2018-9-13 20:16:00 | 显示全部楼层
我对这个也质疑,我看资料上说是支持长文件名,为什么读出来是16进制,我自己转GBK不行吗?
回复 支持 反对

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2097
金钱
2097
注册时间
2014-3-7
在线时间
491 小时
 楼主| 发表于 2018-9-14 08:10:09 | 显示全部楼层
[mw_shl_code=c,true]WCHAR ff_convert ( /* Converted code, 0 means conversion error */
WCHAR src, /* Character code to be converted */
UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
  WCHAR c;
  uint32_t offset; // W25X16地址便宜
  uint8_t GBKH,GBKL; // GBK码高位与低位
  uint8_t unigbk[2]; //
  uint8_t gbkuni[2]; //

  if (src < 0x80) /* ASCII */
  {
    c = src;
  }
  else
  {
    if(dir == 0) /* Unicode to GBK */
    {
      if( (src > 0x4DFF) && (src < 0x9FA6) )
      {
        offset = ((((uint32_t)src - 0x4E00) * 2) + 0x0C0000);
        W25Q16_Read(unigbk,offset,2);
        c = (((uint16_t)unigbk[0])<<8)+(uint16_t)unigbk[1];
      }
      else c = 0xA1A1; //如果是其它符号,都用NULL代替
    }
    else if(dir == 1) /* GBK to Unicode */
    {
      GBKH=(uint8_t)(src>>8);
      GBKL=(uint8_t)(src);
      GBKH-=0x81;
      GBKL-=0x40;
      offset=((uint32_t)192*GBKH+GBKL)*2;
      W25Q16_Read(gbkuni,offset+0x0D0000,2);
      c = (((uint16_t)gbkuni[1])<<8)+(uint16_t)gbkuni[0];
    }
  }
  return c;
}
两张大表放到外部flash,这里就精简很多了吧。
不过,这时候,还是有一些中文符号无法显示,例如常用的书名号《》,中文顿号、,中文双引号 单引号,中文括号【】等都不能显示。这时候,我们可以手动添加进去让其显示,如下:
WCHAR ff_convert ( /* Converted code, 0 means conversion error */
WCHAR src, /* Character code to be converted */
UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */
)
{
  WCHAR c;
  uint32_t offset; // W25X16地址便宜
  uint8_t GBKH,GBKL; // GBK码高位与低位
  uint8_t unigbk[2]; //
  uint8_t gbkuni[2]; //

  if (src < 0x80) /* ASCII */
  {
    c = src;
  }
  else
  {
    if(dir == 0) /* Unicode to GBK */
    {
      switch(src)
      {
      case 0x3001: c = 0xA1A2;break;           // 支持符号: 、 中文顿号
      case 0x300A: c = 0xA1B6;break;     // 支持符号:《
      case 0x300B: c = 0xA1B7;break;            //  支持符号:》
      case 0x201C: c = 0xA1B0;break;           // 支持符号: “        中文左双引号
      case 0x201D: c = 0xA1B1;break;     // 支持符号:”   中文右双引号
      case 0x2606: c = 0xA1EE;break;            //  支持符号:☆
      case 0x2605: c = 0xA1EF;break;           // 支持符号: ★
      case 0x2018: c = 0xA1AE;break;     // 支持符号:‘ 中文左单引号
      case 0x2019: c = 0xA1AF;break;            //  支持符号:’中文右单引号
      case 0x3010: c = 0xA1BE;break;           // 支持符号: 【
      case 0x3011: c = 0xA1BF;break;     // 支持符号: 】
      case 0x3016: c = 0xA1BC;break;            //  支持符号:〖
      case 0x3017: c = 0xA1BD;break;           // 支持符号: 〗
      case 0x2299: c = 0xA1D1;break;     // 支持符号:⊙
      case 0x2116: c = 0xA1ED;break;            //  支持符号:№
      case 0x2236: c = 0xA1C3;break;           // 支持符号: ∶
      case 0x203B: c = 0xA1F9;break;     // 支持符号:※
      case 0x221E: c = 0xA1DE;break;            //  支持符号:∞
      default:
      if( (src > 0x4DFF) && (src < 0x9FA6) )
      {
        offset = ((((uint32_t)src - 0x4E00) * 2) + 0x0C0000);
        W25Q16_Read(unigbk,offset,2);
        c = (((uint16_t)unigbk[0])<<8)+(uint16_t)unigbk[1];
      }
      else c = 0xA1A1; //如果是其它符号,都用NULL代替
      break;
    }
    else if(dir == 1) /* GBK to Unicode */
    {
      GBKH=(uint8_t)(src>>8);
      GBKL=(uint8_t)(src);
      GBKH-=0x81;
      GBKL-=0x40;
      offset=((uint32_t)192*GBKH+GBKL)*2;
      W25Q16_Read(gbkuni,offset+0x0D0000,2);
      c = (((uint16_t)gbkuni[1])<<8)+(uint16_t)gbkuni[0];
    }
  }
  return c;
}
如果你还想支持其他一下特殊符号,可以利用Unicode码和GBK码转换软件自行添加。[/mw_shl_code]caoyugood 发表于 2018-9-13 20:16
我对这个也质疑,我看资料上说是支持长文件名,为什么读出来是16进制,我自己转GBK不行吗?


“长文件名”“短文件名”的详细概念请自行去百度谷歌搜狗搜索。
我们现在只需要知道一个文件名称长了,就是长文件名,例如sdjflasdjfas.txt;一个文件的名称短了,就是短文件名,例如a.txt。
有人会问,文件名干嘛要分长短?这个问题属于计算机历史问题了。想深究,去百度吧。
咱们先看看用“不支持长文件名”的文件系统和“支持长文件名”的文件系统分别读一个比较长的文件名显示的效果吧。
下面是“不支持长文件名”的文件系统读出来的:

下面是“支持长文件名”的文件系统读出来的:

很显然,文件系统如果不支持长文件名,岂能用哉?
以FatFs为例,刚刚移植好的文件系统,默认是不支持长文件名的,要想支持长文件名,需要打开ffconf.h文件进行配置,找到_USE_LFN,把值从0改到1。如下图所示:

改成1以后,任务还没有完成。为了能够支持中文,还需要把_CODE_PAGE的值改为936,如下图所示:

这时候,你编译一下,系统会有如下错误产生:
.\RationEB_Proj.axf: Error: L6218E: Undefined symbol ff_convert (referred from ff.o).
.\RationEB_Proj.axf: Error: L6218E: Undefined symbol ff_wtoupper (referred from ff.o).
Not enough information to list image symbols.
Finished: 1 information, 0 warning and 2 error messages.
".\RationEB_Proj.axf" - 2 Error(s), 0 Warning(s).
提示,找不到ff_convert()和ff_wtoupper()这两个函数。
ff_convert()函数用来把Unicode和GBK之间进行转换。因为文件系统的文件名默认存储方式为Unicode编码,而我们编译器甚至是电脑,用的中文码为GBK。
比如说,现在我要把一个文件名读出来显示到TFT上,当我们读完文件名以后,文件名实际上是由Unicode编码的,这时候,我们就需要找到这些Unicode码对应的GBK码,因为我们的字库是按照GBK编码的,所以需要用到ff_convert()函数里面的Unicode转GBK转换表来转换。由于中文有2万多个汉字,这张转换表实在是太大了,编译不通过,因为单片机容量太小了。所以我们把这张表格放到外部的FLASH吧。
再比如说,我们要在SD卡上新建文件,我们给它的名字是由GBK编码的,而文件名存储,必须是Unicode才行,这时候就需要用到GBK转Unicode的表格。这张表同样很大,所以我们把这张表也放到外部的FLASH里面。
ff_wtoupper()函数是用来英文大小写转换的,比如说,我们把文件名写为ABC.TXT,我们读abc.txt同样会读到这个文件。就是这个文件起的作用。
这两个函数,位于cc936.c文件中,所以我们要把这个文件添加到工程中,cc936.c文件位了FatFs源码的option文件夹当中。
添加好后的工程如下所示:

打开cc936.c文件,ff_wtoupper()文件不用修改。把ff_convert()函数里面的U2G和G2U两张表格数据删除,把函数修改为读取外部的FLASH,来进行U2G和G2U的转换。修改后的函数为:
回复 支持 反对

使用道具 举报

160

主题

967

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2097
金钱
2097
注册时间
2014-3-7
在线时间
491 小时
 楼主| 发表于 2018-9-14 08:12:34 | 显示全部楼层
ssssssssssss 发表于 2018-9-14 08:10
[mw_shl_code=c,true]WCHAR ff_convert ( /* Converted code, 0 means conversion error */
WCHAR src, /* ...

超过8个字符。就叫长文件名了。比如12345678.txt,这是短文件名。
但是:123456789.txt,那就是长文件名了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 17:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表