源:unicode转GBK,GNK转unicode,解决FATFS中文码表占用ROM问题
之前一直使用的512KB ROM的STM32,但是最近使用的只有128KB,想用FATFS显示支持长文件名,发现添加CC936.C后ROM肯定不够的,就决定将这个双向码表存储到外部存储器中,flash或者SD卡都行,只有能读就行;
更改后的CC936.C中的编码转换函数
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; if (src < 0x80) { /* ASCII */ c = src; } else { if (dir) { /* OEMCP to unicode */ c = GBKtoUNICODE(src); } else { /* Unicode to OEMCP */ c = UNICODEtoGBK(src); } } return c; }
删掉那两个码表后,代码瞬间减小了几百KB了.
//我使用的是W25X16 //存储位置说明 //0x00 ~ 0xbc00 存放 UtoG.sys 42kb //0xc000 ~ 0x17c00 存放 GtoU.sys 47kb //0x18000 ~ 0xd3800存放 12x12.ttf 750kb //0xd3c00 ~ 0x18f400 存放 16x16.ttf 750kb //各文件基址 #define CODE_UtoG_BASE (0x00) //unicode转GBK码表 #define CODE_GtoU_BASE (0xC000) //GBK转unicode码表 #define FONT_12X12_BASE (0x18000) //12x12GBK字库 #define FONT_16X16_BASE (0xd3c00) //16x16GBK字库
下面看这两个函数的实现方式
/************************************************************************************************************************* * 函数 : u16 GBKtoUNICODE(u16 GBKCode) * 功能 : 将GBK编码转换为unicode编码 * 参数 : GBK * 返回 : unicode * 依赖 : 底层读写函数 * 作者 : 陈鹏 * 时间 : 20120602 * 最后修改时间 : 20120602 * 说明 : 需要flash中的码表支持GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe *************************************************************************************************************************/ u16 GBKtoUNICODE(u16 GBKCode) { u16 unicode; u8 buff[2]; u16 *p; u8 ch,cl; ch = GBKCode >> 8; cl = GBKCode & 0x00ff; //计算偏移 if(cl < 0x7f) unicode = (ch-0x81)*190+cl-0x40; if(cl > 0x80) unicode = (ch-0x81)*190+cl-0x41; unicode *= 2; W25X16_Read(buff,CODE_GtoU_BASE + unicode,2) ; //读取码表 p = (u16 *)buff; return *p; } /************************************************************************************************************************* * 函数 : u16 UNICODEtoGBK(u16 unicode) * 功能 : 将unicode编码转换为GBK编码 * 参数 : unicode * 返回 : GBK * 依赖 : 底层读写函数 * 作者 : 陈鹏 * 时间 : 20120602 * 最后修改时间 : 20120602 * 说明 : 需要flash中的码表支持GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe *************************************************************************************************************************/ u16 UNICODEtoGBK(u16 unicode) //用二分查找算法 { u32 offset; u8 temp[2]; u16 res; if(unicode<=0X9FA5) offset=unicode-0X4E00; else if(unicode>0X9FA5)//是标点符号 { if(unicode<0XFF01||unicode>0XFF61)return 0;//没有对应编码 offset=unicode-0XFF01+0X9FA6-0X4E00; } W25X16_Read(temp,offset*2+CODE_UtoG_BASE,2);//得到GBK码 res=temp[0]; res<<=8; res+=temp[1]; return res ; //返回找到的编码 }
只要根据自己使用的存储器更改W25X16_Read()这个底层IO接口就行了.