在RT-Thread中正确显示GB2312编码汉字的解决方案如下:
编码不匹配:
E6 AC A2 E8 BF 8E E5 85 89 E4 B8 B4)BB B6 D3 AD B9 E2 C1 D9)根本原因:
// 定义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);
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; // 结束符
}char utf8_str[] = " 欢迎光临 ";
char gb2312_output[32];
utf8_to_gb2312(utf8_str, gb2312_output);
LCMST7920_WriteStringC(0, 0, gb2312_output, 16);检查字库模式:
// ST7920初始化序列(启用中文字库模式)
LCMST7920_WriteCmd(0x0C); // 开显示
LCMST7920_WriteCmd(0x30); // 基本指令集
LCMST7920_WriteCmd(0x06); // 光标右移测试空格显示:
// 应显示正常空格
LCMST7920_WriteStringC(0, 0, "Test Spaces", 11);发送已知GB2312编码:
// 单独测试"欢"字(0xBBB6)
char test_char[] = {0xBB, 0xB6, 0x00};
LCMST7920_WriteStringC(0, 0, test_char, 2);编码获取工具:
"欢迎光临".encode('gb2312').hex(' ').upper()
# 输出:'BB B6 D3 AD B9 E2 C1 D9'内存优化:
RT_SECTION(".rodata"))显示屏兼容性:
推荐方案:对于固定UI文本,直接使用二进制数组(方法1)是最可靠高效的方式。动态内容可采用方法2,但需确保字库表完整覆盖所有用字。
举报
更多回帖