“长文件名”“短文件名”的详细概念请自行去百度谷歌搜狗搜索。
我们现在只需要知道一个文件名称长了,就是长文件名,例如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的转换。修改后的函数为:
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码转换软件自行添加。
想看该例程源文件。可以下载瑞生LPC1114 V3.0开发板资料,位于应用篇例程6。
如何设置FatFs文件系统支持长文件名_eagle11235的博客-CSDN博客
https://blog.csdn.net/eagle11235/article/details/52606089