LCD中文字符显示机制的原理 如何将字符显示到LCD

一、字符显示机制1. 字符显示原理要在lcd上显示一个字符,需要以下两步:
① 占据屏幕上的一块地方,大小由字体大小说了算;② 在占据的地方上依次控制每个像素点是否显示。比如中文字符24×24字体大小表示水平需要24个像素点、垂直需要24个像素点。
在这块24×24的地盘上,每个像素点是否显示由字模说了算,字模中的每1位数据表示一个像素点,如果该位为0则表示此处像素点不显示、为1则表示显示(阴码规则)。
所以,字符显示的函数只需要基于打点函数实现即可。在程序中 逐位读取字模 ,如果该位为0则该点写入背景颜色,如果该位为1则写入前景颜色。
2. 字模生成(点阵字体)正因为lcd显示字符的机制,所以该种字体被称为点阵字体。
为了方便大家理解原理,这里我首先使用小工具生成字模。
设置工具的字模生成规则如下,阴码、逐行式、顺向取模(图中有误)、c51格式:
接着生成汉字的字模:
接着复制生成数据,在程序中定义为一个二维数组作为字库,第一个值表示字库中的元素个数,可以由编译器自行判断,第二个值是每个元素的大小,必须要指明,这样我们就可以用 hz_16x16[0] 来找到汉字 ”春”在字库中的位置:
#ifndef _hz_h_#define _hz_h_const unsigned char hz_16x16[][32] = { {0x01,0x00,0x01,0x00,0x7f,0xfc,0x01,0x00,0x3f,0xf8,0x02,0x00,0xff,0xfe,0x08,0x20,0x10,0x10,0x2f,0xe8,0xc8,0x26,0x08,0x20,0x0f,0xe0,0x08,0x20,0x08,0x20,0x0f,0xe0},/*春,0*//* (16 x 16 , 宋体 )*/};#endif /* _hz_h_*/我们选择的字体是16x16,所以:
水平方向有16个像素点, 每个像素点占1位,需要16bit,两个字节来表示一行 ;垂直方向有16行,所以整体有2*16=32个字节;此处需要注意,软件每16个字节生成一对花括号,这会影响二维数组取值,需要将中间多余的花括号去除。
二、如何将字符显示到lcd1. 打点函数支持字符显示需要打点函数的支持,这里我使用rgb-lcd的打点函数:
void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color);2. 字库支持引入刚刚我们创建二维数组的头文件:
#include hz.h3. 读取字模显示void lcd_show_chinese(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, uint8_t font_size){ uint16_t i, j; uint16_t x_pos, y_pos, size, font_width, font_height; uint8_t *font_ptr; uint8_t bit_width, temp; if((x > (lcd_width - font_size)) || (y > (lcd_height - font_size))) { return; } x_pos = x; y_pos = y; font_height = font_size; font_width = font_size; bit_width = 8; size = (font_width / 8 + ((font_width % 8) ? 1 : 0)) * font_height; font_ptr = (uint8_t*)&hz_16x16[ch]; for (i = 0; i < size; i++) { temp = *(font_ptr + i); for (j = 0; j < bit_width; j++) { if(temp & 0x80){ lcd_draw_point(x_pos, y_pos, font_color); } else { lcd_draw_point(x_pos, y_pos, back_color); } temp < = (x + font_width)) { y_pos++; x_pos = x; } }}实现之后记得声明:
/** * @brief show a chinese char. * @param[in] x1 horizontal start position. * @param[in] y1 vertical start position. * @param[in] x2 horizontal end position. * @param[in] y2 vertical end position. * @param[in] ch offset in hz library. * @param[in] back_color rgb565 * @param[in] font_color rgb565 * @param[in] font_size support 16. * @return none * @note this function need hz library.*/void lcd_show_chinese(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, uint8_t font_size);4. 测试显示在main函数中调用:
lcd_show_chinese(0, 0, 0, black, green, 16);编译、下载即可看到效果
三、小字库的使用1. 制作小字库在项目中,我们需要显示一些中文,但也没必要将整个汉字库包含进来,所以经常是制作本项目专属小字库。
这里取模工具使用安富莱电子的makedot,非常方便:
这里选择了输入文字重排,可以去除重复汉字,减少字库体积。
将生成的整个数组复制作为之前我们创建数组 hz_16x16 的内容:
#ifndef _hz_h_#define _hz_h_const unsigned char hz_16x16[][32] = { {0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,// ! // 0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00},{0x00,0x00,0x20,0x00,0x17,0xfe,0x10,0x08,0x80,0x08,0x43,0xc8,0x42,0x48,0x12,0x48,// 河 // 0x12,0x48,0x22,0x48,0xe3,0xc8,0x22,0x48,0x20,0x08,0x20,0x08,0x20,0x28,0x00,0x10},{0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x7c,0xfe,0x44,0x12,0x44,0x12,0x44,0x12,0x44,// 加 // 0x12,0x44,0x12,0x44,0x12,0x44,0x12,0x44,0x22,0x44,0x22,0x7c,0x4a,0x44,0x84,0x00},{0x01,0x00,0x01,0x00,0xff,0xfe,0x01,0x00,0x01,0x00,0x7f,0xfc,0x48,0x24,0x44,0x44,// 南 // 0x4f,0xe4,0x41,0x04,0x41,0x04,0x5f,0xf4,0x41,0x04,0x41,0x04,0x41,0x14,0x40,0x08},{0x00,0x40,0x20,0x40,0x10,0x40,0x10,0x40,0x87,0xfc,0x44,0x44,0x44,0x44,0x14,0x44,// 油 // 0x14,0x44,0x27,0xfc,0xe4,0x44,0x24,0x44,0x24,0x44,0x24,0x44,0x27,0xfc,0x04,0x04},};#endif /* _hz_h_*/这样就完成了我们整个项目小字库的制作,同样的方法,我们再制作出hz_24x24字库,hz_32x32字库。
const unsigned char hz_24x24[][72] = { //...};const unsigned char hz_32x32[][128] = {};2. 使用小字库进一步完善中文显示函数,找到获取字模数据的代码:
font_ptr = (uint8_t*)&hz_16x16[ch]优化为:
switch (font_size) { case 16: font_ptr = (uint8_t*)&hz_16x16[ch]; break; case 24: font_ptr = (uint8_t*)&hz_24x24[ch]; break; case 32: font_ptr = (uint8_t*)&hz_32x32[ch]; break; default: return;}在main函数中进一步添加测试程序:
lcd_show_chinese(0, 0, 1, black, red, 16); // 河lcd_show_chinese(16, 0, 3, black, red, 16); // 南lcd_show_chinese(32, 0, 2, black, red, 16); // 加lcd_show_chinese(48, 0, 4, black, red, 16); // 油lcd_show_chinese(64, 0, 0, black, red, 16); // !lcd_show_chinese(0, 20, 1, black, red, 24);lcd_show_chinese(24, 20, 3, black, red, 24);lcd_show_chinese(48, 20, 2, black, red, 24);lcd_show_chinese(72, 20, 4, black, red, 24);lcd_show_chinese(96, 20, 0, black, red, 24);lcd_show_chinese(0, 60, 1, black, red, 32);lcd_show_chinese(32, 60, 3, black, red, 32);lcd_show_chinese(64, 60, 2, black, red, 32);lcd_show_chinese(96, 60, 4, black, red, 32);lcd_show_chinese(128, 60, 0, black, red, 32);四、进一步的优化本文中讲述的仅仅是最基本的中文显示方法,还可以进一步进行优化。
① 字符偏移优化
这里使用小字库不太方便的点是,字符在字库中的偏移位置需要自己控制,如果想自动控制就涉及编码问题,实现后可以直接写汉字字符串来显示。
② 字库优化
项目中比较稳妥的办法是使用全字库,片内flash肯定不够用,通常的做法是外挂一片spi flash,将整个全字库文件烧写到flash里,使用的时候读出来即可。
③ 字体优化
本文中我们取模时都使用的是宋体,好不容易建立的字库,可能某天老板突然过来说要换成什么奇奇怪怪的字体,那不是完蛋了~
所以在实现的时候我们要考虑在spi flash上建立文件系统,直接使用文件,方便字库文件替换。

关于甲烷变送器在矿井安全生产中的作用
浅析4个计算机视觉领域常用迁移学习模型
7月上汽通用五菱以破万产量紧随特斯拉之后,位居第二
除了“卷”,汽车市场仿佛已无处可去
华为Mate 30 Pro将采用接近90°的曲面屏设计屏占比超高
LCD中文字符显示机制的原理 如何将字符显示到LCD
带你认识平板电视DLNA功能
IE无法浏览网页的常见原因及解决方法
基于FPGA的PCB测试机硬件电路设计研究
尼康A900相机拥有2029万的有效像素,搭载了更多的闪光灯功能
通用汽车部署24台3D打印机,推动3D打印技术在汽车产业的发展
工业智能网关是什么?和NAT转换网关有什么区别?
电源设计经验:电源外围MOV及TVS选型篇
西安航空利用工业互联网产品提供云计算等多种类型的云服务
全自动量热仪的安装与实验
汽车芯片短缺的影响:汽车价格上涨
格力电器公布“具有防病毒传播功能的隔离装置、电梯”专利
人工智能在生命科学上是如何应用的
博升光电获近亿元人民币A+轮融资 将主要用于量产及新品研发
高智能测土配方施肥仪的工作原理是怎样的