本帖最后由 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.Arduino对汉字转换、显示后,结果不正常(第二行是将正常编码赋值给变量并显示的结果)
一开始我以为是代码中计算汉字的字库点阵的地址有问题,于是尝试获取字库中所有单元的点阵数据,期待着用这些数据拼接成字符,从而了解字库的构成。结果一是数据量太大,二是得到一些奇怪的数据,根本无法组成正常的字符,最终放弃了。于是选择技术咨询,问了厂家技术人员。技术人员说在Keil下的有个处理BUG,并给我发了一个程序,用于解决这个BUG。可我是在Arduino下处理的,不存在这个问题啊。
无奈之下,想到另外一个办法:既然能大量销售,显示模块的字库不会有问题,那么一定是程序的问题。我试着把直接输出字符串改成赋值到变量中,然后利用串口的输入输出功能和屏幕能正常输出数字、英文字符的特点,按照16进制方式输出这个unsigned char数组变量的每一个元素,发现汉字并没有被转换为正常的两字节数据。也没细想为什么会这样,我就是利用数组成员再赋值的方式写入正常的两字节16进制数据(汉字对应的16进制表达,可以通过电脑端由串口输出汉字给开发板,在开发板测显示数据方式得到),并把要显示的汉字提到数组最前面,结果液晶屏把这个汉字正常显示了出来显示。到这一步,可以证明从字库中提取汉字点阵的代码是没有问题的,计算地址的方式是对的。然后进一步的测试发现每个汉字被转换为3个字节的数据。发现这个结果的瞬间,就想到了编码的问题,虽然都是使用C语言开发,但是不是在Arduino中对汉字做了其它编码转换,导致汉字编程三个字节的数据?于是上网查了查,果然在Arduino中使用UTF8编码方式,会自动把汉字转换为3字节的数据。
图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.Arduino自动转换的汉字编码和正确汉字编码的对比
如果不想这么麻烦,想一步就位,一个办法是,利用代码将UTF8数据转换为GB2312数据,这个就需要一些转码方面的知识了。我上网查了查,看到的解决办法是,将UTF8转成UNICODE后,然后利用查找法找到汉字对应的数据,再转成GB2312。UNICODE转GB2312需要有大量的对比数据支撑,会比较消耗空间,对于开发板不合适,我没有采用。还有一个办法是改变Arduino的底层设置,使Arduino使用GB2312方式处理字符串,这个办法是有一定风险的。我担心会引起其他的问题,也不在我的考虑之列。准备有时间,在彻底弄懂UTF8的编码机制后,找找规律,看看有没有快捷的什么处理方式,把字转为GB2312。
测试使用ESP8266开发板,附上测试代码:
test_ok.zip
(7.79 KB)
|
牛 这个应该是原创了。