FATFS外置UNICODE GBK双向转换码表(转)

源:FATFS外置UNICODE GBK双向转换码表

将UtoG,GtoU双向码表放到存储卡里面实现长文件名,因为FATFS长文件名需要unicode支持,

首先将UtoG.sys,GtoU.sys两个文件放到SD卡根目录,注意,一定要在根目录,并且是短文件名,因为长文件名需要UNICODE支持,此时的FATFS还是不支持长文件名的,但是当初始化UNICODE码表后就可以支持长文件名了.

两个码表下载地址:http://download.csdn.net/detail/cp1300/5526739

附上C代码

/*************************************************************************************************************
 * 文件名:    unicode_gbk.c
 * 功能:        汉字编码转换
 * 作者:        cp1300@139.com
 * 创建时间:    2013-04-03
 * 最后修改时间:2013-04-03
 * 详细:        需要码表支持
*************************************************************************************************************/
#include "system.h"
#include "unicode_gbk.h"



#define GBK_UNICODE_IS_SDCARD    1    //GBK,UNICODE编码表在SD卡或其它存储器中




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//码表在SD卡中
#if GBK_UNICODE_IS_SDCARD

#include "ff.h"
#define GtoU    "0:/GtoU.sys"         //GBK 转 UCICODE 编码表位置
#define UtoG    "0:/UtoG.sys"        //UCICODE 转 GBK 编码表位置

static     FIL   GtoU_File;            //GtoU 文件工作区
static     FIL   UtoG_File;            //UtoG 文件工作区


/*************************************************************************************************************************
* 函数    :    u8 GBK_UNICODE_Init(void)
* 功能    :    初始化GBK,UNICODE编码表
* 参数    :    无    
* 返回    :    0:初始化成功;其它:初始化失败
* 依赖    :    底层读写函数
* 作者    :    cp1300@139.com
* 时间    :    2013-04-18
* 最后修改时间 : 2013-04-18
* 说明    :     无
*************************************************************************************************************************/ 
u8 GBK_UNICODE_Init(void)
{
     FRESULT status;

    status = f_open(&UtoG_File, UtoG, FA_OPEN_EXISTING | FA_READ);    //以只读方式打开UNICODEtoGBK码表,打开失败返回错误
    if(status != FR_OK)    //打开失败
    {
        uart_printf("open %s error (%d)!
",UtoG, status);
        return 1;
    }

    status = f_open(&GtoU_File, GtoU, FA_OPEN_EXISTING | FA_READ);    //以只读方式打开GBKtoUNICODE码表,打开失败返回错误
    if(status != FR_OK)    //打开失败
    {
        uart_printf("open %s error (%d)!
",GtoU, status);
        return 1;
    }


    return 0;
}




/*************************************************************************************************************************
* 函数    :    u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能    :    将GBK编码转换为unicode编码
* 参数    :    GBK    
* 返回    :    unicode
* 依赖    :    底层读写函数
* 作者    :    cp1300@139.com
* 时间    :    20120602
* 最后修改时间 : 20120602
* 说明    :     需要flash中的码表支持
            GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
    u8 ch,cl;
    UINT bw;
    u16 data;

    ch = GBKCode >> 8;
    cl = GBKCode & 0x00ff;

    ch -= 0x81;
    cl -= 0x40;
    
    f_lseek(&GtoU_File, (ch*0xbf+cl)*2);                        //文件指针调到偏移位置
    if(f_read(&GtoU_File, (u8 *)&data, 2, &bw) != FR_OK)        //读取2字节
    {
       return 0x1fff;
    }
    
    return (ch<=0x7d && cl<=0xbe) ? data : 0x1fff;



   /*    ch = GBKCode >> 8;
    cl = GBKCode & 0x00ff;

    ch -= 0x81;
    cl -= 0x40;    
    return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;       */

}



/*************************************************************************************************************************
* 函数    :    u16 OneUNICODEtoGBK(u16 unicode)
* 功能    :    将unicode编码转换为GBK编码
* 参数    :    unicode
* 返回    :    GBK    
* 依赖    :    底层读写函数
* 作者    :    cp1300@139.com
* 时间    :    20120602
* 最后修改时间 : 20120602
* 说明    :     需要flash中的码表支持
            GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法
{
    u32 offset;
    u16 temp;
    UINT bw;
    u8 buff[2];

    if(unicode<=0X9FA5)
    {
        if(unicode>=0X4E00)
            offset=unicode-0X4E00;//0x1b87        //0X4E00,汉字偏移起点
        else
            return 0x2020;        //不能显示的字符就给两个空格填充,否则乱码
    }    
    else if(unicode>0X9FA5)//是标点符号
    {
        if(unicode<0XFF01||unicode>0XFF61)
            return 0x2020;//没有对应编码    //不能显示的字符就给两个空格填充,否则乱码
        offset=unicode-0XFF01+0X9FA6-0X4E00;    
    }
    offset *= 2;


    f_lseek(&UtoG_File, offset);                        //文件指针调到偏移位置
    if(f_read(&UtoG_File, buff, 2, &bw) != FR_OK)    //读取2字节
    {
       return 0x2020;
    }

    temp = buff[0];
    temp <<= 8;
    temp += buff[1];
    return temp;    //返回找到的编码                 
}











////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#else                                //码表直接在代码中
#include "unicode_gbk_code.h"


/*************************************************************************************************************************
* 函数    :    u8 GBK_UNICODE_Init(void)
* 功能    :    初始化GBK,UNICODE编码表
* 参数    :    无    
* 返回    :    0:初始化成功;其它:初始化失败
* 依赖    :    底层读写函数
* 作者    :    cp1300@139.com
* 时间    :    2013-04-18
* 最后修改时间 : 2013-04-18
* 说明    :     无
*************************************************************************************************************************/ 
u8 GBK_UNICODE_Init(void)
{
    return 0;
}




/*************************************************************************************************************************
* 函数    :    u16 OneGBKtoUNICODE(u16 GBKCode)
* 功能    :    将GBK编码转换为unicode编码
* 参数    :    GBK    
* 返回    :    unicode
* 依赖    :    底层读写函数
* 作者    :    cp1300@139.com
* 时间    :    20120602
* 最后修改时间 : 20120602
* 说明    :     需要flash中的码表支持
            GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneGBKtoUNICODE(u16 GBKCode)
{
    u8 ch,cl;

    ch = GBKCode >> 8;
    cl = GBKCode & 0x00ff;

    ch -= 0x81;
    cl -= 0x40;
    return (ch<=0x7d && cl<=0xbe) ? wUnicodes[ch*0xbf+cl] : 0x1fff;

}



/*************************************************************************************************************************
* 函数    :    u16 OneUNICODEtoGBK(u16 unicode)
* 功能    :    将unicode编码转换为GBK编码
* 参数    :    unicode
* 返回    :    GBK    
* 依赖    :    底层读写函数
* 作者    :    cp1300@139.com
* 时间    :    20120602
* 最后修改时间 : 20120602
* 说明    :     需要flash中的码表支持
            GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
u16 OneUNICODEtoGBK(u16 unicode)  //用二分查找算法
{
    u32 offset;
    u16 temp;

    if(unicode<=0X9FA5)
    {
        if(unicode>=0X4E00)
            offset=unicode-0X4E00;//0x1b87        //0X4E00,汉字偏移起点
        else
            return 0x2020;        //不能显示的字符就给两个空格填充,否则乱码
    }    
    else if(unicode>0X9FA5)//是标点符号
    {
        if(unicode<0XFF01||unicode>0XFF61)
            return 0x2020;//没有对应编码    //不能显示的字符就给两个空格填充,否则乱码
        offset=unicode-0XFF01+0X9FA6-0X4E00;    
    }
    offset *= 2;
    
    temp = wGBKs[offset];
    temp <<= 8;
    temp += wGBKs[offset+1];
    return temp;    //返回找到的编码                 
}


#endif //GBK_UNICODE_IS_SDCARD



/*************************************************************************************************************************
* 函数    :    void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
* 功能    :    将多个GBK编码转换为UNICODE
* 参数    :    pGBK:GBK编码缓冲区
*             pUnicode:UNCODE编码缓冲区
*             cnt:转换编码个数
* 返回    :    无    
* 依赖    :    OneGBKtoUNICODE
* 作者    :    cp1300@139.com
* 时间    :    20130403
* 最后修改时间 : 20130403
* 说明    :     需要flash中的码表支持
            GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void GBKToUnicode(u16 *pGBK, u16 *pUnicode, u32 cnt)
{
    while(cnt --)
    {
        *pUnicode = OneGBKtoUNICODE(*pGBK ++);
        pUnicode ++;
    }
}




/*************************************************************************************************************************
* 函数    :    void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
* 功能    :    将多个UNICODE编码转换为GBK
* 参数    :    pUnicode:UNCODE编码缓冲区
*             pGBK:GBK编码缓冲区
*             cnt:转换编码个数
* 返回    :    无    
* 依赖    :    OneUNICODEtoGBK
* 作者    :    cp1300@139.com
* 时间    :    20130403
* 最后修改时间 : 20130403
* 说明    :     需要flash中的码表支持
            GBK码范围,高8位:0x81~0xfe;低8位:0x40~0xfe
*************************************************************************************************************************/ 
void UnicodeToGBK(u16 *pUnicode, u16 *pGBK, u32 cnt)
{
    while(cnt --)
    {
        *pGBK = OneUNICODEtoGBK(*pUnicode ++);
        pGBK ++;
    }
}

修改cc963.c,FATFS的unicode编码支持文件

修改以下这个函数,主要讲这个文件里面的两个编码表注释掉,以实现节省单片机FLASH的目的。

#include "unicode_gbk.h" //编码转换
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 = OneGBKtoUNICODE(src);
        } 
        else 
        {        /* Unicode to OEMCP */
            c = OneUNICODEtoGBK(src);
        }
    }

    return c;
}
#endif

这样只要在初始化了FATFS之后马上初始化码表就可以实现用占用FLASH实现长文件名的支持,我的这个不光用在FATFS里面,还用在GSM模块的短信编码,解码上面。

原文地址:https://www.cnblogs.com/LittleTiger/p/4681936.html