发新帖本帖赏金 20.00元(功能说明)我要提问
返回列表
[UNO]

Arduino下对字符串处理的问题

[复制链接]
22366|2
手机看帖
扫描二维码
随时随地手机跟帖
suncat0504|  楼主 | 2023-1-13 09:34 | 显示全部楼层 |阅读模式
本帖最后由 suncat0504 于 2023-1-16 19:34 编辑

#申请原创#
@21小跑堂
      为了测试刚入手的带汉字字库的晶联讯液晶显示模块(JLX25696G-966-PL),用Arduino开发板写了测试程序,结果发现一些有趣的问题。买之前,以为带字库的,就像LCD1602那样,只需要把要显示的字符串发给液晶就可以正常显示呢,结果到手认真看了看液晶的说明资料,并咨询厂家技术人员,才搞明白。这个液晶模块在显示字符的时候,需要通过专用的接口从模块自带的字库中取得点阵数据,然后再通过另外的接口发给液晶,才能正常显示字符。如果不使用字库,也可以自己在代码中组织字符的点阵数据,通过程序查找匹配,得到点阵数据,直接发给液晶显示。
我手里有三种开发板:自己作的51系列的开发板,ARM32位开发板以及Arduino开发板。由于液晶是使用3.3V的电源,对于51单片机,只能使用支持3.3V的,手里有AT89C2051/4051,以及STC15W4K32系列的单片机,但它们的程序下载,都需要利用其它设备下载。从开发、编译、下载、测试角度考虑有点繁琐,而ARM32位开发板的开发,需要编写太多代码,所以考虑来考虑去,就用Arduino开发板吧。这样方便很多。需要说明的是,如果想带着字库驱动液晶,需要使用到以下接口,共计10个IO口线:

引 线
符 号
名 称
功 能
1
ROM_IN
字库IC接口
字库串行数据输入
2
ROM_OUT
字库IC接口
字库串行数据输出
3
ROM_SCK
字库IC接口
字库串行时钟
4
ROM_CS
字库IC接口
字库片选输入
5
LEDA
背光电源
背光电源正极,3.3V(已加限流电阻)
6
VSS
供电电源负极
供电电源负极
7
VDD
供电电源正极
供电电源正极 3.3V
8
A0(RS)
寄存器选择信号
串行时钟 SCK
9
RST
复位
低电平复位,复位完成后,回到高电平,液晶模块开始工作
10
CS
片选
低电平片选
11
D7
I/O
悬空或接 VDD
12
D6
I/O
寄存器选择信号RS:0-指令,1-数据
13-18
D5-D0
I/O
悬空或接 VDD
19
RD(E)
读功能
悬空或接 VDD
20
WR
写功能
悬空
表 1:模块的接口引脚功能 (只表示串口模式下的符号和功能)
      按照说明书中的例程,进行了必要的改造,编译、下载程序到开发板,断电,连接好接口后,给开发板上电,可以看到显示结果了。但很奇怪的是,所有数字、符号、英文字母的显示都是正常的,但汉字的显示却是乱码的。比如说把“简体字”显示为“绠浣瀛”。
1.jpg

图1.Arduino对汉字转换、显示后,结果不正常(第二行是将正常编码赋值给变量并显示的结果)


     一开始我以为是代码中计算汉字的字库点阵的地址有问题,于是尝试获取字库中所有单元的点阵数据,期待着用这些数据拼接成字符,从而了解字库的构成。结果一是数据量太大,二是得到一些奇怪的数据,根本无法组成正常的字符,最终放弃了。于是选择技术咨询,问了厂家技术人员。技术人员说在Keil下的有个处理BUG,并给我发了一个程序,用于解决这个BUG。可我是在Arduino下处理的,不存在这个问题啊。
      无奈之下,想到另外一个办法:既然能大量销售,显示模块的字库不会有问题,那么一定是程序的问题。我试着把直接输出字符串改成赋值到变量中,然后利用串口的输入输出功能和屏幕能正常输出数字、英文字符的特点,按照16进制方式输出这个unsigned char数组变量的每一个元素,发现汉字并没有被转换为正常的两字节数据。也没细想为什么会这样,我就是利用数组成员再赋值的方式写入正常的两字节16进制数据(汉字对应的16进制表达,可以通过电脑端由串口输出汉字给开发板,在开发板测显示数据方式得到),并把要显示的汉字提到数组最前面,结果液晶屏把这个汉字正常显示了出来显示。到这一步,可以证明从字库中提取汉字点阵的代码是没有问题的,计算地址的方式是对的。然后进一步的测试发现每个汉字被转换为3个字节的数据。发现这个结果的瞬间,就想到了编码的问题,虽然都是使用C语言开发,但是不是在Arduino中对汉字做了其它编码转换,导致汉字编程三个字节的数据?于是上网查了查,果然在Arduino中使用UTF8编码方式,会自动把汉字转换为3字节的数据。
2.png

图2.通过串口输出Arduino下汉字的转换结果


      知道了原因就好办了,为了能让屏幕正常显示汉字,不使用汉字直接赋值或者作为参数提供给屏幕输出函数,而是用数组赋值正确的16进制数值的方式来显示汉字就可以了。虽然这种方式是比较繁琐的,需要你获得汉字对应的16进制表达。
Arduino下含有汉字的字符串:
unsigned char tmp[]="简体字参 GB2312,16X16";
display_GB2312_16x16_string(1,1, tmp);

赋值为正常编码的处理代码:
  tmp[0]=0xBC;   // 简
  tmp[1]=0xF2;
  tmp[2]=0xCC;  // 体
  tmp[3]=0xE5;
  tmp[4]=0xD7;  // 字
  tmp[5]=0xD6;
  tmp[6]=0xB2;   // 参
  tmp[7]=0xCE;
  tmp[8]=0xCC;   // 体
  tmp[9]=0xE5;
  tmp[10]=0xD7;  // 字
  tmp[11]=0xD6;  
  display_GB2312_16x16_string(1,3, tmp);


3.png

图3.Arduino自动转换的汉字编码和正确汉字编码的对比


     如果不想这么麻烦,想一步就位,一个办法是,利用代码将UTF8数据转换为GB2312数据,这个就需要一些转码方面的知识了。我上网查了查,看到的解决办法是,将UTF8转成UNICODE后,然后利用查找法找到汉字对应的数据,再转成GB2312。UNICODE转GB2312需要有大量的对比数据支撑,会比较消耗空间,对于开发板不合适,我没有采用。还有一个办法是改变Arduino的底层设置,使Arduino使用GB2312方式处理字符串,这个办法是有一定风险的。我担心会引起其他的问题,也不在我的考虑之列。准备有时间,在彻底弄懂UTF8的编码机制后,找找规律,看看有没有快捷的什么处理方式,把字转为GB2312。

测试使用ESP8266开发板,附上测试代码: test_ok.zip (7.79 KB)

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 20.00 元 2023-01-17
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
cooldog123pp 2023-7-12 12:53 回复TA
牛 这个应该是原创了。 

相关帖子

gaochy1126| | 2023-2-18 15:02 | 显示全部楼层
为什么不使用arduino和w25q32做一个字库显示汉字?  

使用特权

评论回复
发新帖 本帖赏金 20.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:大连伊飞特信息技术有限公司软件工程师
简介:本人于1993年毕业于大连理工大学。毕业后从事单片机开发工作5年,之后转入软件开发工作至今。

93

主题

2675

帖子

5

粉丝