stm32h743单片机嵌入式学习笔记5-液晶屏汉字库原理
液晶屏使用的汉字库的原理:
*每个汉字由多个点组成,即点阵,比如16号字体(实际上电脑对字号的叫法和点阵大小不一样,实际上这个电脑成为12号字体,原谅下面我也叫16号字体),就是16*16的点阵,即32个字节的数据,那么每一个字体的点阵由点阵取模软件可以得到
*同号大小字体所有汉字取模后的点阵数据顺序往后存放,那么我们怎么找到每一个汉字对应的点阵数据呢,然后进行液晶屏画点函数即可显示出该函数,这是通过把每一个汉字进行编码(就像人的身份证号),那就叫做汉字内码。
汉字在各种文件里面的存储不是以点阵数据的形式存储的(否则那占用的空间就太大了),而是以内码的形式存储的,就是
GB2312/GBK/BIG5 等这几种的一种,每个汉字对应着一个内码,在知道了内码之后再去字库里面查找这个汉字的点阵数据,然后在液晶上显示出来。这里我举个例,比如我们打开记事本,随便敲两个16号大小的字,然后保存,这个txt文件占的大小应该是4字节,而不是2*32=64字节,我们去看看这个文件属性,果然是占用4字节。
那这里的4个字节到底存了什么呢,刚刚说了每一个汉字都对应一个汉字内码(汉字的ID),以GBK这种汉字编码方式为例,每个 GBK 码由 2 个字节组成,第一个字节为大小范围0X81~0XFE(称为高字节GBKH),第二个字节(称为低字节GBKL),有两个汉字,所以就占4个字节了。有了一个汉字的内码和字体大小后通过一个计算公式就可以定位到这个汉字对应的点阵数据了(因为汉字取模时候每个汉字的点阵数据都是依次往后存放的,不需要文件系统的方式以文件形式存放,就是在外部flash芯片中顺序存放即可,这样单片机不需要上文件系统就能使用字库),然后在液晶屏上面绘制出来即可。对应的就是这个查找函数
//code 字符指针开始
//从字库中查找出字模
//code 字符串的开始地址,GBK码,是一个数组,包含了高字节和低字节
//mat 数据存放地址 (size/8+((size%8)?1:0))*(size) bytes大小 ,这个指针就得到了这个汉字对应的点阵数据
//size:字体大小
void Get_HzMat(unsigned char *code,unsigned char *mat,u8 size)
{
unsigned char qh,ql;
unsigned char i;
unsigned long foffset;
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数
qh=*code;
ql=*(++code);
if(qh<0x81||ql<0x40||ql==0xff||qh==0xff)//非 常用汉字
{
for(i=0;i<csize;i++)*mat++=0x00;//填充满格
return; //结束访问
}
if(ql<0x7f)ql-=0x40;//注意!
else ql-=0x41;
qh-=0x81;
foffset=((unsigned long)190*qh+ql)*csize; //得到字库中的字节偏移量,这个就是计算公式,可能每一种汉字编码可能公式不一样,但是原理是一样的
switch(size)
{
case 12:
W25QXX_Read(mat,foffset+ftinfo.f12addr,csize); // 这里我们已经事先知道了每个字号字体库的起始地址
break;
case 16:
W25QXX_Read(mat,foffset+ftinfo.f16addr,csize);
break;
case 24:
W25QXX_Read(mat,foffset+ftinfo.f24addr,csize);
break;
case 32:
W25QXX_Read(mat,foffset+ftinfo.f32addr,csize);
break;
}
}
上层显示函数就是:
//显示一个指定大小的汉字
//x,y :汉字的坐标
//font:汉字GBK码
//size:字体大小
//mode:0,正常显示,1,叠加显示
void Show_Font(u16 x,u16 y,u8 *font,u8 size,u8 mode)
------------------------------------------------------------------------------------------------------------------------------------------------
上面说完了汉字库以及显示原理,接下来说一下单片机如何实现的:
单片机上电后,会检测外部flash芯片里是否有字库,原理:正点原子事先约定了在外部flash芯片(32MB的)的25MB的位置开始存放字库信息头结构体 ftinfo,然后依次往后紧接着存放UNIGBK转换码表(这个是干啥的,文章末尾我会进行单独介绍),GBK12,16,24,32四种字体。
//字体信息保存地址,占41个字节,第1个字节用于标记字库是否存在.后续每8个字节一组,分别保存起始地址和文件大小
extern u32 FONTINFOADDR;
//字库信息结构体定义
//用来保存字库基本信息,地址,大小等
__packed typedef struct
{
u8 fontok; //字库存在标志,0XAA,字库正常;其他,字库不存在
u32 ugbkaddr; //unigbk的地址
u32 ugbksize; //unigbk的大小
u32 f12addr; //gbk12地址
u32 gbk12size; //gbk12的大小
u32 f16addr; //gbk16地址
u32 gbk16size; //gbk16的大小
u32 f24addr; //gbk24地址
u32 gbk24size; //gbk24的大小
u32 f32addr; //gbk32地址
u32 gbk32size; //gbk32的大小
}_font_info;
通过检测上面的字库存在标志就能知道字库存在与否,如果不存在,那么我们就得进行字库更新,即从插入的sd卡(提前在电脑上制作好的字库以文件形式放在sd卡里)中依次读取字库文件存放到flash中来即可。
接下来讲解一下更新字库的过程:
读取sd卡中事先做好的几个字库文件
//字库存放在磁盘(sd卡)中的路径
u8*const GBK_PATH[5]=
{
"/SYSTEM/FONT/UNIGBK.BIN", //UNIGBK.BIN的存放位置
"/SYSTEM/FONT/GBK12.FON", //GBK12的存放位置
"/SYSTEM/FONT/GBK16.FON", //GBK16的存放位置
"/SYSTEM/FONT/GBK24.FON", //GBK24的存放位置
"/SYSTEM/FONT/GBK32.FON", //GBK32的存放位置
};
然后
res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ); // fxpath就是字库的全路径
case 0: //更新UNIGBK.BIN
ftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo); //信息头之后,紧跟UNIGBK转换码表
ftinfo.ugbksize=fftemp->obj.objsize; //UNIGBK大小
flashaddr=ftinfo.ugbkaddr;
break;
case 1:
ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize; //UNIGBK之后,紧跟GBK12字库
ftinfo.gbk12size=fftemp->obj.objsize; //GBK12字库大小
flashaddr=ftinfo.f12addr; //GBK12的起始地址
break;
case 2:
ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size; //GBK12之后,紧跟GBK16字库
ftinfo.gbk16size=fftemp->obj.objsize; //GBK16字库大小
flashaddr=ftinfo.f16addr; //GBK16的起始地址
break;
。。。。。。
上面是设置信息头结构体的每个字库起始地址信息等等,然后就要读取复制sd卡字库内容进入外部flash了
while(res==FR_OK)//死循环执行
{
res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //读取数据
if(res!=FR_OK)break; //执行错误
W25QXX_Write(tempbuf,offx+flashaddr,4096); //从0开始写入4096个数据 ,读取复制sd卡字库内容进入外部flash
offx+=bread;
fupd_prog(x,y,size,fftemp->obj.objsize,offx); //进度显示
if(bread!=4096)break; //说明读完了,因为没有读到想要的4096个,就说明不够读了,就是完成了
}
最后保存上信息头结构体内容进入外部flash即可,同时置字库存在标志为0XAA
//全部更新好了
ftinfo.fontok=0XAA;
W25QXX_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //保存字库信息
---------------------------------------------------------------------------------------------------------------------------------------------
关于 UNIGBK转换码表 的作用:
文件系统中要用 ffunicode.c,以支持长文件名,但是 ffunicode.c 文件里面中文转换
(中文的页面编码代号为:936)的两个数组太大了(172KB),直接刷在单片机里面,太占用
flash 了,所以我们必须把这两个数组存放在外部 flash
将 C 语言数组转换为.bin 文件,然后只需要将 UNIGBK.bin 保存到外部 FLASH
就实现了该数组的转移
ffunicode.c中的代码 W25QXX_Read((u8*)&t,ftinfo.ugbkaddr+i*4+gbk2uni_offset,4);//读出 4 个字节
就是实现从外部flash读取出那两个大数组
stm32h743单片机嵌入式学习笔记5-液晶屏汉字库原理相关推荐
- stm32h743单片机嵌入式学习笔记6-压缩图片解码原理
软件解码: JPEG/JPG 的解码过程可以简单的概述为如下几个部分: 1 .从文件头读出文件的相关信息. JPEG 文件数据分为文件头和图像数据两大部分,其中文件头记录了图像的版本. 长宽.采样因子 ...
- stm32h743单片机嵌入式学习笔记7-FPU
* FPU 即浮点运算单元(Float Point Unit).浮点运算,对于定点 CPU(没有 FPU 的 CPU) 来说必须要按照 IEEE-754 标准的算法来完成运算,是相当耗费时间的.而对于 ...
- stm32h743单片机嵌入式学习笔记4-文件系统FATFS
FAT32 文件系统 就是在格式化的时候 选择 FAT32 方式格式化. 然后在 SD 卡存储区会产生一个类似于 目录 的文件系统. 这样存入 SD 卡中的所有 文件 文件夹 都会在这个目录中找到. ...
- 51单片机学习笔记-12LCD1602液晶屏
12 LCD1602液晶屏 [toc] 注:笔记主要参考B站江科大自化协教学视频"51单片机入门教程-2020版 程序全程纯手打 从零开始入门". 注:工程及代码文件放在了本人的G ...
- 嵌入式学习笔记——基于Cortex-M的单片机介绍
基于Cortex-M的单片机介绍 前言 1生产厂商及其产品线 1.1ARM单片机的产品线 1.2命名规则 作业1 2习单片机的资料准备 2.1STM32开发所需手册 2.1.1芯片的数据手册 芯片基本 ...
- 嵌入式学习笔记——ADC模数转换器
ADC模数转换器 前言 ADC介绍 ADC概述 ADC的数量 ADC的特性 ADC框图 芯片外部框图 芯片内部框图 转换部分框图 状态输出部分 条件触发框图 寄存器介绍 编程思路 模式选择 规则通道的 ...
- cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)
cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断) https://blog.csdn.net/qq_16255321/article/details/43086 ...
- 嵌入式学习笔记——STM32的USART通信概述
文章目录 前言 常用通信协议分类及其特征介绍 通信协议 通信协议分类 1.同步异步通信 2.全双工/半双工/单工 3.现场总线/板级总线 4. 串行/并行通信 5. 有线通信.无线通信 STM32通信 ...
- 嵌入式学习笔记--jlink 工具RTT使用笔记
嵌入式学习笔记–jlink 工具RTT 使用笔记 最近有调试一个ethcat板卡的需求,板卡设计的很简洁,没有多余的调试串口,正准备飞线到单片机针脚上的时候发现了RTT 的这个工具,记录一下使用的方法 ...
- 嵌入式学习笔记——使用寄存器编程操作GPIO
使用寄存器编程操作GPIO 前言 GPIO相关的寄存器 GPIO 端口模式寄存器 (GPIOx_MODER) (x = A..I) 位操作 GPIO 端口输出类型寄存器 (GPIOx_OTYPER) ...
最新文章
- python 定义空集合 和定义空字典的
- 构筑超异构计算时代,英特尔 AI 全布局
- ASP.Net中自定义Http处理及应用之HttpHandler篇
- prometheus rfc3339 php date 转换
- Hadoop 2.4.1+HBase 0.98.6.1 分布式安装
- 天才王垠惊人言论炸翻网友:相对论是假说,爱因斯坦是民科!
- IOS 8.0 适配应用图片设计
- 自动化创建tornado项目
- 机器学习与深度学习基础概念介绍
- matlab 7.0布局,Matlab 7.0 装配指导
- Linux打开终端命令
- java ssh框架是什么_JAVA SSH框架介绍
- html5如何添加图片菜鸟教程,菜鸟入门教程 HTML5的常见用法
- 成本会计的概念、产品成本核算的要求、产品成本核算的对象与成本项目、产品成本的归集和分配(可能考判断)、产品成本计算方法 (三种:产品的品种(品种法),批次(分批法),步骤(分步法))
- 2020年《财富》世界500强排行榜揭晓
- 小米手机系统服务组件是干什么的_小米手机的云服务也太好用了吧?!手机丢了完全不用怕了...
- flutter能开发游戏吗_Flutter Flame游戏开发上手(1)
- 哈夫曼树的构造与哈夫曼编码
- 用电脑怎么快速抠图?怎么把图片抠成透明背景?
- 油画特效软件akvis artwork破解版安装及破解教程
热门文章
- [iOS]让你的应用支持新iPad的Retina显示屏
- 景区门票预约系统_景区门票预订系统有哪些功能
- 2020UNCTF-MISC-网络深处1
- Kaldi 使用,egs下通用样例及功能小结
- 2021-09-23 latex 实心圆编号
- 问题记录1:网络和共享中心打不开的解决办法
- Spring Boot 整合 AWS S3协议 OSS功能 支持 七牛、阿里、Minio等一切支持S3协议的云厂商
- Unity 贴花/喷漆功能的原理、Projector组件的原理与优化
- 计算机桌面有阴影,电脑桌面图标有蓝色阴影 怎么去除桌面图标阴影
- mysql 多表左连接查询