×

LVGL学习------LVGL+FATFS字体编码不兼容

zxjy辉 zxjy辉 发表于2022-12-30 09:32:05 浏览359 评论0

抢沙发发表评论


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

克罗地亚普利特维采湖自然风光.jpeg

  1. 具体原因

    1. 在利用FATFS读取目录下(如SD卡里的目录)的文件名的时候 ,读取到的文件名是GBK编码的(通常情况下,中国大陆的PC默认的编码是GBK的,而不是UTF-8编码,导致了这个读取后,在LVGL上显示就会乱码(FATFS读取不会错的原因:FATFS是采用字节流读取的,不是字符流所以没有问题)),

  2. 解决办法

    1. 第一种:将PC更改为UTF-8的编码的,这样之后,就没什么大问题,但是有一个问题,就是电脑端的一些软件是不支持UTF-8编码的中文,导致中文显示乱码(例如keil的中文注释就会显示乱码),并且要更改SD卡的内容时,也要是UTF-8编码的电脑

    2. 第二种:就是做一个编码转换,将读取到的文件名(GBK)转换为Unicode编码再转换为UTF-8编码,然后,再给LVGL使用,这样就不会出现乱码。其他电脑也能使用。

  3. 编码转换方法

    1. GBK转Unicode使用的是查表的方法,通过对照表查找到对应的内码GBK转Unicode对照表.tx

    2. //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;
      }
    3. //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;  
      }


    4. 最后就是字符串的GBK转UTF-8 ,如e所示

    5. /*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;
              }
          }
      }
#好好学习!

群贤毕至

访客