RT-Thread论坛
直播中

周臻庸

8年用户 907经验值
私信 关注
[问答]

rt-thread程序中的汉字字符串,如何提取汉字的gb2312编码?

我希望程序中的汉字字串“欢迎光临”取出来的字节数组是GB2312码:“BB B6 D3 AD B9 E2 C1 D9 00”,
而实际出来的是UTF-8码:“E6 AC A2 E8 BF 8E E5 85 89 E4 B8 B4 00”,
转成大端UTF16-BE是:“6B 22 8F CE 51 49 4E 34 00”,
用的一个带GB2312字库的12864显示屏LCM,
直接用LCMST7920_WriteStringC(0,0,"    欢迎光临    ",16);
出来的是乱码(前后各有四个空格,空格显示正常,汉字显示乱码)


回帖(1)

王银喜

2025-10-13 18:08:57

在RT-Thread中正确显示GB2312编码汉字的解决方案如下:


问题分析




  1. 编码不匹配



    • RT-Thread默认使用UTF-8编码(如“欢迎光临”的UTF-8字节:E6 AC A2 E8 BF 8E E5 85 89 E4 B8 B4

    • 你的12864液晶屏(ST7920控制器)需要GB2312编码(正确字节应为:BB B6 D3 AD B9 E2 C1 D9

    • 直接发送UTF-8字符串导致乱码




  2. 根本原因



    • 显示屏字库芯片内置GB2312编码点阵,需直接输入GB2312码值

    • UTF-8编码格式不被支持






解决方案


方法1:直接使用GB2312编码的二进制数组(推荐)


// 定义GB2312编码的字符串(含前后空格)
char gb2312_str[] = {
    0x20, 0x20, 0x20, 0x20,  // 4个空格(ASCII)
    0xBB, 0xB6,              // 欢
    0xD3, 0xAD,              // 迎
    0xB9, 0xE2,              // 光
    0xC1, 0xD9,              // 临
    0x20, 0x20, 0x20, 0x20,  // 4个空格
    0x00                     // 结束符
};

// 发送到显示屏
LCMST7920_WriteStringC(0, 0, gb2312_str, 16);

方法2:动态转换UTF-8到GB2312(需码表)



  1. 创建汉字映射表

    typedef struct {
    const char *utf8;  // UTF-8编码(3字节)
    uint16_t gb2312;   // GB2312编码(2字节)
    } CharMap;


static const CharMap gb2312_table[] = {
{"欢", 0xBBB6},  // UTF-8: E6ACA2
{"迎", 0xD3AD},  // UTF-8: E8BF8E
{"光", 0xB9E2},  // UTF-8: E58589
{"临", 0xC1D9},  // UTF-8: E4B8B4
// 添加其他汉字...
};



2. **转换函数**:
```c
void utf8_to_gb2312(const char *src, char *dest) {
    while (*src) {
        if ((*src & 0x80) == 0) { // ASCII字符
            *dest++ = *src++;
        } else { // 中文字符
            char utf8_char[4] = {src[0], src[1], src[2], 0};
            src += 3;

            // 在表中查找匹配项
            uint16_t gb_code = 0;
            for (int i = 0; i < sizeof(gb2312_table)/sizeof(CharMap); i++) {
                if (memcmp(utf8_char, gb2312_table[i].utf8, 3) == 0) {
                    gb_code = gb2312_table[i].gb2312;
                    break;
                }
            }

            if (gb_code) {
                *dest++ = gb_code >> 8;    // 高字节
                *dest++ = gb_code & 0xFF;  // 低字节
            }
        }
    }
    *dest = 0; // 结束符
}


  1. 使用示例
    char utf8_str[] = "    欢迎光临    ";
    char gb2312_output[32];
    utf8_to_gb2312(utf8_str, gb2312_output);
    LCMST7920_WriteStringC(0, 0, gb2312_output, 16);




关键验证步骤




  1. 检查字库模式


    // ST7920初始化序列(启用中文字库模式)
    LCMST7920_WriteCmd(0x0C);      // 开显示
    LCMST7920_WriteCmd(0x30);      // 基本指令集
    LCMST7920_WriteCmd(0x06);      // 光标右移



  2. 测试空格显示


    // 应显示正常空格
    LCMST7920_WriteStringC(0, 0, "Test Spaces", 11);



  3. 发送已知GB2312编码


    // 单独测试"欢"字(0xBBB6)
    char test_char[] = {0xBB, 0xB6, 0x00};
    LCMST7920_WriteStringC(0, 0, test_char, 2);





注意事项




  1. 编码获取工具



    • 使用Python快速获取GB2312编码:
      "欢迎光临".encode('gb2312').hex(' ').upper()
      # 输出:'BB B6 D3 AD B9 E2 C1 D9'




  2. 内存优化



    • 方法2的码表建议置于段(RT_SECTION(".rodata")

    • 仅包含项目实际用到的汉字以减少体积




  3. 显示屏兼容性



    • 确认ST7920固件支持GB2312(部分克隆芯片仅支持ASCII)

    • 检查硬件连接:PSB引脚需置高(并行模式)





推荐方案:对于固定UI文本,直接使用二进制数组(方法1)是最可靠高效的方式。动态内容可采用方法2,但需确保字库表完整覆盖所有用字。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分