历史上的今天
返回首页

历史上的今天

今天是:2024年10月27日(星期日)

正在发生

2021年10月27日 | stm32专题二十二:液晶显示中英文 字符编码

2021-10-27 来源:eefocus

字符编码


字符编码及转换测试:http://www.qqxiuzi.cn/daohang.htm


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

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

ASCII 编码


ASCII编码(单字节),标准ASCII编码只使用了0 ~ 127,而128 ~ 255属于扩展编码,不属于标准ASCII。

不可见编码(0 ~ 31):

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

GB2312编码

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


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


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

GB2312兼容ASCII编码:

区位码表示:

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

计算实例:

GB2312的部分区位表:

GBK编码


GBK编码,加入了更多的繁体字和生僻字,同时兼容了GB2312编码:


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从160 = 0XA0开始编码),要把区号和位号都偏移160(即 + 0XA0),得到GB2312编码:

计算公式如下:

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


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

推荐阅读

史海拾趣

GWP Group公司的发展小趣事

针对晶体二极管单相全波电阻负载整流电路,网友可能提出多个问题,以下是一些可能的问题及其详细回答:

1. 什么是晶体二极管单相全波电阻负载整流电路?

回答:晶体二极管单相全波电阻负载整流电路是一种将交流电(AC)转换为直流电(DC)的电路,它利用了晶体二极管的单向导电特性。这种电路通过四个二极管(通常构成桥式整流器)实现全波整流,即同时利用交流电的正负半周进行整流,从而提高整流效率。负载电阻则用于消耗整流后的直流电。

2. 该电路的工作原理是什么?

回答:晶体二极管单相全波电阻负载整流电路的工作原理基于二极管的单向导电性。在交流电的正半周,二极管D1和D3导通,D2和D4截止,电流通过D1、负载电阻和D3形成回路,负载上得到上正下负的电压。在交流电的负半周,情况相反,D2和D4导通,D1和D3截止,电流方向不变,同样通过负载电阻,从而在负载上持续得到方向不变的直流电压。

3. 为什么需要四个二极管而不是两个?

回答:使用四个二极管构成桥式整流器可以充分利用交流电的正负两个半周,实现全波整流。如果只使用两个二极管,则只能实现半波整流,即只利用交流电的一个半周进行整流,整流效率较低。桥式整流电路通过巧妙地连接四个二极管,使得在每个半周内都有电流通过负载,从而提高了整流效率。

4. 如何提高该电路的整流效率?

回答:提高晶体二极管单相全波电阻负载整流电路的整流效率可以从以下几个方面入手:

  • 选择合适的变压器:根据整流电路的输入电压和输出电压要求,选择合适的变压器,以保证整流电路的稳定性和效率。
  • 优化整流器设计:通过选择合适的二极管和优化整流器的布局,可以提高整流器的整流效率和稳定性。
  • 增加滤波电路:在整流器的输出端增加滤波电路(如电容和电感),可以滤除整流后的脉动直流电中的交流成分,得到更加平滑的直流电,从而提高整流效率。

5. 该电路有哪些应用?

回答:晶体二极管单相全波电阻负载整流电路具有广泛的应用,包括但不限于以下几个方面:

  • 电源适配器:将交流电转换为直流电,为各种电子设备提供稳定的电源。
  • 充电器:用于为电池充电,将交流电转换为适合电池充电的直流电。
  • 电源模块:作为电源模块的一部分,为各种电子设备提供稳定的直流电源。
  • 工业控制:在工业控制领域,为各种控制设备提供稳定的直流电源。

6. 该电路是否存在局限性?

回答:尽管晶体二极管单相全波电阻负载整流电路具有许多优点,但也存在一些局限性。例如,整流后的直流电仍存在一定的脉动成分,需要通过滤波电路进一步处理;此外,整流过程中会产生一定的能量损失,包括二极管的正向导通压降和滤波电路中的能量损耗等。因此,在实际应用中需要根据具体需求选择合适的整流电路和滤波方案。

Asia Pacific Microsystems Inc公司的发展小趣事

随着电子行业的快速发展,APM意识到只有不断创新才能在市场中立足。于是,公司加大了对研发的投入,积极引进高端人才,并与多所高校和研究机构建立了合作关系。经过几年的努力,APM成功研发出了一款具有自主知识产权的高性能模拟芯片,填补了国内市场的空白。这款芯片在信号处理、通信等领域具有广泛应用前景,为APM带来了可观的收益。

Elpida Memory公司的发展小趣事

尽管Elpida Memory已经不复存在,但其在DRAM领域的技术和经验仍然对全球半导体产业产生了深远的影响。Elpida Memory在技术研发、生产管理和市场营销等方面的经验,为后来的半导体企业提供了宝贵的借鉴和参考。同时,Elpida Memory的失败也提醒了半导体企业需要时刻保持警惕和创新精神,以应对日益激烈的市场竞争和技术变革。

Avasem公司的发展小趣事

Avasem公司深知人才是企业发展的核心驱动力。因此,公司一直致力于构建良好的人才培养机制和企业文化。Avasem公司注重员工的个人成长和职业发展,提供丰富的培训和学习机会,鼓励员工不断学习和创新。同时,公司还倡导开放、包容和协作的企业文化,为员工创造一个积极、健康的工作环境。这种以人为本的管理理念不仅吸引了大量优秀人才加入公司,还激发了员工的创新精神和团队凝聚力,为公司的持续发展提供了有力保障。

Cedrat Technologies公司的发展小趣事

在电子行业中,振动控制是一个至关重要的领域。Cedrat Technologies凭借其在压电技术领域的深厚积累,成功开发了一套主动振动控制系统。该系统通过精确监测机械结构或设备的振动情况,利用压电执行器产生相位相反的振动信号,有效抵消原始振动。这一技术的问世,不仅大幅提升了设备的稳定性和精度,也为机械结构的振动控制开辟了新的途径。Cedrat Technologies因此在电子行业中树立了新的技术标杆。

Arduino公司的发展小趣事

随着Arduino电路板的成功推出,Arduino平台在2005年发布了第一款主板——Arduino NG。这款主板采用了Atmel公司的AVR单片机作为核心处理器,并结合了简单易用的开发环境。这一创新使得普通人也能够轻松地进行单片机编程和硬件开发,大大降低了电子制作的门槛。Arduino NG的发布标志着Arduino平台开始受到开发者和爱好者的广泛关注。

问答坊 | AI 解惑

无法下载啊

我怎么下不了东西呢?…

查看全部问答>

OS 和库文件集

介绍了 Xilinx 微内核、其组成库、单独的板支持包以及各种版本的 VxWorks 和 Linux 操作系统的板支持包。…

查看全部问答>

PPP协议搞不定,谁能给点建议啊,资料也可以啊!

PPP协议搞不定,谁能给点建议啊,资料也可以啊!急!…

查看全部问答>

高分请教ozi,ozf2等等

小弟在windows ce 做开发,以前用过bmp,jpeg的格式,但这两种文件占内存太大,所以我想使用ozf2格式文件,现在一直没找到这方面的资料,各位大虾帮帮小弟啊 谢谢大家给点建议,有代码最好了!我的邮箱是:zhuyaqi2004@sohu.com …

查看全部问答>

各位,加速度传感器MMA7455,那俩中断怎么解?

各位,加速度传感器MMA7455,那俩中断怎么解?加速度传感器MMA7455,那俩中断怎么解…

查看全部问答>

关于s3c2410 ADCCON寄存器结束转换的讨论

rADCCON = rADCCON | (1<<0); // 启动ADC    while(rADCCON & 0x01); // 等待ADC启动        while(!(rADCCON & 0x8000)); // 等待ADC完成我疑惑了,ADCCON不是16位寄存器吗?第15bit是结束标志位,为什 ...…

查看全部问答>

MSP430的NRF24L01程序

谁有MSP430的NRF24L01程序,板子最好是427或是261X  谢谢啦   可以的话给我发一份吧  邮箱是 min910203@163.com 谢谢。。。。…

查看全部问答>

【好书推荐】平凡的探索-单片机工程师与教师的思考

内容推荐 本书通过一系列单片机项目开发案例的分析,有侧重地展示各个案例,包括作者开发过程中曾走过的弯路,尽可能地启迪读者的思维,教给读者“学习与开发”的方法。 本书共分15章,第1章介绍开发环境,其余各章分别针对一个案例进行介绍。 ...…

查看全部问答>

P1OUT = 0xff;和P1OUT |= 0xff;的区别几问题

这个问题我好像在刚开始接触msp430 的时候遇到过,现在又再次碰到了。花了我好长时间!郁闷。 P1OUT = 0xff;输出就是0xff; P1OUT |= 0xff; 那输出是什么呢?比如在液晶1602的写操作中:void 1602writecom(unsigned char com) {    RS_0 ...…

查看全部问答>

科普:浅谈PCB业余制作,兼答雕刻机制作PCB

一般来说,业余制作PCB板,不外乎三种原理。 1. 机械的:     手工刀刻,小时候俺常用的方法。     自动化的用雕刻机雕刻。 2. 物理的:     用激光,众所周知,激光定位对横纵向(X,Y轴,左右前后)定位准 ...…

查看全部问答>