液晶显示中英文 字符编码

本文详细介绍了字符编码体系,包括ASCII、GB2312、GBK、GB18030、Big5以及Unicode编码,着重讨论了在LCD显示中的应用,如字模原理、GB2312编码的区位码转换和字库生成方法。
摘要由CSDN通过智能技术生成

字符编码及转换测试:导航菜单 - 千千秀字

这个网站可以查询汉字字符编码,如下图所示:

输入汉字,就可以查询字符编码:

ASCII 编码

不可见编码(0 ~ 31):

可见字符编码(32 ~ 127):

GB2312编码

全角和半角的区别(一般都使用半角,很少使用全角):

      角就是字母和数字等与汉字占等宽位置的字。 半角就是ASCII方式的字符,在没有汉字输入法起作用的时候输入的字母数字和字符都是半角的。

例如,字符B,全角GB2312编码为A3C2,半角ASCII编码为0X42。

GB2312兼容ASCII编码:

区位码转成GB2312(GB2312从160 = 0XA0开始编码),要把区号和位号都偏移160(即 + 0XA0),得到GB2312编码:

计算实例:

GB2312的部分区位表:

GBK编码

 

GB18030编码

Big5编码,港台地区使用 

 Unicode 字符集和编码 

Unicode编码的出现,为了统一全世界不同的字符。Unicode把这些字符进行编号,而没有进行编码。

 编号和编码的区别?

如字符 'A' ,在ASCII中为0X41 = 65,也就是说, 'A' 的编号是65,而ASCII的编码是一个字节0X41,也可以用两个字节表示

0X 00 41,或者三个字节表示 0X 00 00 41。编号就是 0 1 2 3这些简单的数字,而编码实际上是编成了计算机二进制码。编码要包含 (到底是一个字节表示,或者两个字节表示,或者数据大小端)等信息。
Unicode编号和GB2312汉字编码的区别:

Unicode 字符编码格式

不同风格的Unicode编码描述:

 UTF-32(直接把编号和编码同等对应,使用4字节)

 可以看到,UTF-32编码,对于使用英语地区的国家,实际上是非常不友好的,原来使用单字节能表示的字符,为了兼容Unicode,现在要使用4个字节存储,增加了3倍的存储空间。还有,Unicode产生之前的那些文件,就统统失效不能使用。所以,UTF-32根本无法推行。

注意,UTF-32并不兼容ASCII编码,如采用UTF-32,会使得原来老的文件全部乱码,所以无法推广。

UTF-16

UTF-8 编码

完全兼容了ASCII编码,也使用了变长编码,可以节省存储空间。但对于中文而言,GB2312编码使用2字节,而UTF-8平均要使用3字节,所以有些网站为了节省存储空间,还是采用了GB2312编码格式。 

UTF-8编码思路:

BOM 编码格式

字模原理

 

字模的构成: 

如果采用的是 16*16 点阵显示,每个字模要占用32字节的空间。如果是英文,总共128个字符,占用的空间为 4KB。而常用的中文汉字有6000+,用字模表示,大概要占用200KB的空间,这对存储容量的要求是非常大的。

字模的生成(使用软件PCtoLCD2002):

生成的字模数据为:

{0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x80,0x04,0x1F,0xE0,0x00,0x40,0x00,0x80,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00},
{0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00},/*"字",0*/

根据生成的字模数据,我们利用串口打印来验证一下,是否图形显示正确:

/* 生成的字模数据 */
uint8_t test_module[] = {0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x80,0x04,
	0x1F,0xE0,0x00,0x40,0x00,0x80,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,
	0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00};	/*"字",0*/
 
void Display_char_test(void)
{
	uint8_t i = 0, j = 0, k = 0;
	
	/* 字模数据有16行 */
	for (i = 0; i < 16; i++)
	{
		/* 每行16列,2字节 */
		for (j = 0; j < 2; j++)
		{
			/* 每个字节8位 */
			for (k = 0; k < 8; k++)
			{
				/* 对每个数据字节从高位到低位进行遍历 */
				if ((test_module[i * 2 + j] & (0X80 >> (k))) != 0)
				{
					printf("*");
				}
				else
				{
					printf(" ");
				}
			}
		}
		printf("\n");
	}
}

串口打印结果如下:

联想到之前液晶显示的程序,液晶显示的原理就是开窗,然后不断的填入16位颜色数据(RGB565格式),如果按照串口输出的做法,在字模数据为为 1 处显示白色,为 0 处显示黑色,就可以打印字模对应的文字(黑底白字)。

/**
  * @brief 画一个实心的矩形
  */
void ILI9341_Darw_Rec(void)
{
	uint32_t i = 0;
	
	ILI9341_Open_Window(10, 20, 50, 100);
	
	ILI9341_Write_Cmd(CMD_SetPixel);	// 填充像素
	
	for (i = 0; i < 50 * 100; i++)
	{
		ILI9341_Write_Data(RGB888_TO_RGB565(0, 255, 0));			// 对应绿色
	}
}

现在还剩下一个问题,如果我们希望在程序中直接给出一个字符串,液晶屏就能显示出来,怎么做?

一个能想到的处理方式就是,在数组中添加很多个字的字模,然后想要显示那个字,直接加上对应的偏移就可以,如下:

/* 生成的字模数据 */
uint8_t test_module[] = {
	0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,0x21,
	0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,
	0x21,0x08,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,		/* 中 */
 
	0x00,0x00,0x7F,0xFC,0x40,0x04,0x40,0x04,0x5F,0xF4,0x41,
	0x04,0x41,0x04,0x4F,0xE4,0x41,0x04,0x41,0x44,0x41,0x24,
	0x5F,0xF4,0x40,0x04,0x40,0x04,0x7F,0xFC,0x40,0x04			/* 国 */
};
 
 
void Display_char_test(void)
{
	uint8_t i = 0, j = 0, k = 0;
	
	/* 字模数据有16行 */
	for (i = 0; i < 16; i++)
	{
		/* 每行16列,2字节 */
		for (j = 0; j < 2; j++)
		{
			/* 每个字节8位 */
			for (k = 0; k < 8; k++)
			{
				/* 对每个数据字节从高位到低位进行遍历 */
				if ((test_module[ 32 + i * 2 + j] & (0X80 >> (k))) != 0)
				{
					printf("*");
				}
				else
				{
					printf(" ");
				}
			}
		}
		printf("\n");
	}
}

当使用偏移(+32)时,就可以显示第二个汉字,这样就可以打印多个文字。

如何制作字模

根据使用要求制作字模 如何建立映射关系?

        比如GB2312汉字编码,如果每个字符是32字节(16*16点阵),如果想显示两个字,只要适当的安排偏移,每个汉字占的字模大小都是32字节,这样只需要算好偏移就可以。如果按照GB2312编码表来安排,如第 0 ~ 31字节存储“啊”,第 32 ~ 63字节存储“阿”,第64 ~ 95字节存储“埃”...,我们希望能制作出这样的字模,字模中包含我们需要的编码表的所有字符且有固定映射。
我们希望实现的函数:

ILI9341_DispStringLine_EN_CH(LINE(2),"ILI9341液晶驱动");

  如果能把字符串转换成对应的字符编码,那么就能直接输入字符串,再调用lcd屏来显示。怎么把字符串转换成编码?这个和MDK软件的配置有关。按照GB2312的编码规则,像前面的ILI9341都是单字节编码,而汉字液晶驱动就会对应的转成双字节的GB2312编码。我们就可以直接通过字符串的形式,编写一个函数,根据他的编码,来找到字模数据。一旦找到字模数据,后面就好办了,直接根据之前的字模显示原理,打印出字模。

如何生成字库?

PCtoLCD软件的配置:

设置字模显示区域大小和字模大小:

字模寻址公式推导:

先看ASCII表的字模寻址,这个相对比较简单(每个字模固定16字节):

我们制作的字模数组,从空格开始,接下来的字符依次偏移 16 字节。所以,ASCII字库中,每个字符的起始索引计算:

索引下标计算公式:('A' - ' ') * 16                相对于空格的偏移 * 每个字符的大小。

GB2312字模(区位码):

每个字模的大小为:16 * 16 / 8 = 32字节

第 0 个字节存储的是空格,根据区号和位号,求出字符相对于空格的偏移,然后*字符大小,就能求出数组下标索引。

区位码转成GB2312(GB2312从161 = 0XA1开始编码),要把区号和位号都偏移160(即 + 0XA0)(区号和位号都是从1开始),得到GB2312编码:

GBH-0XA0得到GB2312对应字符的区号,再减去空格所在区号0x01,就得到相对于空格区号的偏移;94 是指一个区中有 94 个位(94 个字符)

GBL-0XA0得到GB2312对应字符的位号,再减去空格所在位号0x01,就得到相对于空格位号的偏移;区位码总的差的字符数乘以每个字符占据的字节数32,求出地址偏移。

计算公式如下:

像这种字符串,编译器会根据mdk设置,把英文编译成ASCII编码,把中文编译成GB2312编码,如下:

ILI9341_DispStringLine_EN_CH(LINE(2),"ILI9341液晶驱动");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值