前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LCD中文字符显示机制

LCD中文字符显示机制

作者头像
Mculover666
发布2021-08-20 10:35:00
2.2K0
发布2021-08-20 10:35:00
举报
文章被收录于专栏:TencentOS-tinyTencentOS-tiny

一、字符显示机制

1. 字符显示原理

要在LCD上显示一个字符,需要以下两步:

  • ① 占据屏幕上的一块地方,大小由字体大小说了算;
  • ② 在占据的地方上依次控制每个像素点是否显示。

比如中文字符24×24字体大小表示水平需要24个像素点、垂直需要24个像素点。

在这块24×24的地盘上,每个像素点是否显示由字模说了算,字模中的每1位数据表示一个像素点,如果该位为0则表示此处像素点不显示、为1则表示显示(阴码规则)。

所以,字符显示的函数只需要基于打点函数实现即可。在程序中逐位读取字模,如果该位为0则该点写入背景颜色,如果该位为1则写入前景颜色。

图片
图片

2. 字模生成(点阵字体)

正因为LCD显示字符的机制,所以该种字体被称为点阵字体。

为了方便大家理解原理,这里我首先使用小工具生成字模。

设置工具的字模生成规则如下,阴码、逐行式、顺向取模(图中有误)、C51格式:

图片
图片

接着生成汉字的字模:

图片
图片

接着复制生成数据,在程序中定义为一个二维数组作为字库,第一个值表示字库中的元素个数,可以由编译器自行判断,第二个值是每个元素的大小,必须要指明,这样我们就可以用 hz_16x16[0] 来找到汉字 ”春”在字库中的位置:

代码语言:javascript
复制
#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个字节生成一对花括号,这会影响二维数组取值,需要将中间多余的花括号去除。

二、如何将字符显示到LCD

1. 打点函数支持

字符显示需要打点函数的支持,这里我使用RGB-LCD的打点函数:

代码语言:javascript
复制
void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color);

2. 字库支持

引入刚刚我们创建二维数组的头文件:

代码语言:javascript
复制
#include "hz.h"

3. 读取字模显示

代码语言:javascript
复制
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 <<= 1;
            x_pos++;
        }
        if (x_pos >= (x + font_width)) {
            y_pos++;
            x_pos = x;
        }
    }
}

实现之后记得声明:

代码语言:javascript
复制
/**
 * @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函数中调用:

代码语言:javascript
复制
lcd_show_chinese(0, 0, 0, BLACK, GREEN, 16);

编译、下载即可看到效果:

图片
图片

三、小字库的使用

1. 制作小字库

在项目中,我们需要显示一些中文,但也没必要将整个汉字库包含进来,所以经常是制作本项目专属小字库。

这里取模工具使用安富莱电子的MakeDot,非常方便:

图片
图片

这里选择了输入文字重排,可以去除重复汉字,减少字库体积。

将生成的整个数组复制作为之前我们创建数组 hz_16x16 的内容:

代码语言:javascript
复制
#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字库。

代码语言:javascript
复制
const unsigned char hz_24x24[][72] = {
 //...
};

const unsigned char hz_32x32[][128] = {

};

2. 使用小字库

进一步完善中文显示函数,找到获取字模数据的代码:

代码语言:javascript
复制
font_ptr = (uint8_t*)&hz_16x16[ch]

优化为:

代码语言:javascript
复制
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函数中进一步添加测试程序:

代码语言:javascript
复制
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上建立文件系统,直接使用文件,方便字库文件替换。

后续这些优化点我也会写文章分享,这个周末要出去逛吃逛吃啦~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Mculover666 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、字符显示机制
    • 1. 字符显示原理
      • 2. 字模生成(点阵字体)
      • 二、如何将字符显示到LCD
        • 1. 打点函数支持
          • 2. 字库支持
            • 3. 读取字模显示
              • 4. 测试显示
              • 三、小字库的使用
                • 1. 制作小字库
                  • 2. 使用小字库
                    • 四、进一步的优化
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档