LVGL 采用的是UTF-8编码,而FATFS采用的是Unicode编码,这两种编码在显示字符的时候,是一样的,但是在显示中文的时候是会出问题的

具体原因
在利用FATFS读取目录下(如SD卡里的目录)的文件名的时候 ,读取到的文件名是GBK编码的(通常情况下,中国大陆的PC默认的编码是GBK的,而不是UTF-8编码,导致了这个读取后,在LVGL上显示就会乱码(FATFS读取不会错的原因:FATFS是采用字节流读取的,不是字符流所以没有问题)),
解决办法
第一种:将PC更改为UTF-8的编码的,这样之后,就没什么大问题,但是有一个问题,就是电脑端的一些软件是不支持UTF-8编码的中文,导致中文显示乱码(例如keil的中文注释就会显示乱码),并且要更改SD卡的内容时,也要是UTF-8编码的电脑
第二种:就是做一个编码转换,将读取到的文件名(GBK)转换为Unicode编码再转换为UTF-8编码,然后,再给LVGL使用,这样就不会出现乱码。其他电脑也能使用。
编码转换方法
GBK转Unicode使用的是查表的方法,通过对照表查找到对应的内码
GBK转Unicode对照表.tx//GBK转Unicode编码的方法如下,要用到3.a的编码对照表(是一个超大的数组) ///将传入的单个字符GBK码转为unicode码 WCHAR my_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; //这个就是GBK转Unicode的对照表的数组方法名 hi = sizeof oem2uni / 4 - 1; } // else { /* Unicode to OEMCP */ // p = uni2oem; //这个是Unicode转GBK的对照表的数组方法名(没用到) // 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; }//Unicode转UTF-8 //这个直接用函数就可以实现 ///Unicode 转 utf-8 int enc_unicode_to_utf8_one(unsigned long unic,unsigned char *pOutput) { // assert(pOutput != NULL); if (unic <= 0x0000007F) { // * U-00000000 - U-0000007F: 0xxxxxxx *pOutput = (unic & 0x7F); return 1; } else if (unic >= 0x00000080 && unic <= 0x000007FF) { // * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx *(pOutput + 1) = (unic & 0x3F) | 0x80; *pOutput = ((unic >> 6) & 0x1F) | 0xC0; return 2; } else if (unic >= 0x00000800 && unic <= 0x0000FFFF) { // * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx *(pOutput + 2) = (unic & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 6) & 0x3F) | 0x80; *pOutput = ((unic >> 12) & 0x0F) | 0xE0; return 3; } else if (unic >= 0x00010000 && unic <= 0x001FFFFF) { // * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput + 3) = (unic & 0x3F) | 0x80; *(pOutput + 2) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 12) & 0x3F) | 0x80; *pOutput = ((unic >> 18) & 0x07) | 0xF0; return 4; } else if (unic >= 0x00200000 && unic <= 0x03FFFFFF) { // * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput + 4) = (unic & 0x3F) | 0x80; *(pOutput + 3) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput + 2) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 18) & 0x3F) | 0x80; *pOutput = ((unic >> 24) & 0x03) | 0xF8; return 5; } else if (unic >= 0x04000000 && unic <= 0x7FFFFFFF) { // * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput + 5) = (unic & 0x3F) | 0x80; *(pOutput + 4) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput + 3) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput + 2) = ((unic >> 18) & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 24) & 0x3F) | 0x80; *pOutput = ((unic >> 30) & 0x01) | 0xFC; return 6; } return 0; }最后就是字符串的GBK转UTF-8 ,如e所示
/*gbk 指向gbk字串的指针【输入】 *utf8 指向utf8字串的指针【输出】 --------------------*/ void StringGBK2UTF8(uint8_t *gbk, uint8_t *utf8) { int i = 0; while (gbk[i] != 0) { if (gbk[i] < 0x80) { *utf8 = gbk[i]; utf8++; i++; } else { // printf("GBK:%s\r\n", gbk); WCHAR unico = my_ff_convert((WCHAR)(gbk[i] << 8 | gbk[i+1]),1); // printf( "unicode:%d\r\n", unico); int byte = enc_unicode_to_utf8_one(unico, utf8); utf8 += byte; i = i + 2; } } }
#好好学习!