在屏幕上显示字库中汉字

  • 显示原理
  • 字体模型
    • 1.取模
    • 2.字库
  • 显示函数的实现
    • 1.首先实现点亮一个点
    • 2.以汉字12 * 12,字符6 * 12为例写的驱动函数
    • 3.显示函数(集成到一个函数中)
  • 总结
最近在搞屏幕,顺便弄了一个字库芯片,刚刚测试完毕。个人认为项目中人机交互是少不了的,而显示是人机交互中的重要一环,所以准备写一篇教程记录一下。

显示原理

首先要知道屏幕显示的原理。屏幕显示的原理其实很简单,其实就是和点阵一样,只不过屏幕集成度高,本质控制输出高或者低,跟点灯一样。   
拿0.96寸的oled来举个例子。0.96oled分辨率128*64,也就是说横向128个led,竖向64个led,你想点亮某个led(假设1为亮,0为灭),那么只需要将那个led对应的位置1即可。那如何显示汉字呢。其实原理也是一样的。如下图所示,只需要将对应的点点亮,而这些对应的点可以拼成一个汉字的模样。 

再具体一点就是,单片机将想要显示的点的数据通过spi或者iic传给屏幕驱动芯片,屏幕驱动得到命令后就会将对应的点点亮,具体怎么点后面介绍。 

字体模型

看到这里可能会有疑问,我不可能每个汉字都去照着样子去点亮led吧?那多费劲!
确实费劲,不过有简单的方法。1.取模 2.用字库(本质还是取模)

1.取模

什么是取模?就上上图看到的一样,将汉字对应的点转换成单片机能识别的二进制数去点亮led,从而显示到屏幕上。只不过这一步可以用软件自动生成,不需要你自己比对这汉字去一个一个点点儿了。下面是三个字取模之后得到的数组,我们只需要将汉字输入到软件中,点击生成字模就行了,是不是很简单。
嵌(0) 入(1) 式(2){0x01,0x80,0x31,0x8C,0x31,0x8C,0x3F,0xFC,0x00,0x30,0x33,0x30,0x33,0x3F,0xFF,0xE3},
{0x33,0xDE,0x33,0x18,0x3F,0x18,0x33,0x18,0x33,0x3C,0x3F,0x3C,0x33,0x66,0x00,0xC3},/*"嵌",0*/{0x06,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x03,0xC0,0x03,0xC0,0x03,0xC0},
{0x06,0x60,0x06,0x60,0x0C,0x30,0x0C,0x30,0x18,0x18,0x30,0x18,0x60,0x0C,0xC0,0x07},/*"入",1*/{0x00,0x6C,0x00,0x66,0x00,0x66,0x00,0x60,0xFF,0xFF,0x00,0x60,0x00,0x60,0x3F,0x60},
{0x0C,0x60,0x0C,0x60,0x0C,0x30,0x0C,0x33,0x0F,0x9B,0x7C,0x0F,0x30,0x07,0x00,0x03},/*"式",2*/

2.字库

字库其实是个芯片,比如GT21L16S2Y、GT30L32S4W等,它是将取好的字模按照一定标准存放在内存当中,本质还是取模。这个标准遵循GB2312,是个国标。还有别的标准,比如UTF-8、GBK等等。
code  +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
B3A0     场 尝 常 长 偿 肠 厂 敞 畅 唱 倡 超 抄 钞 朝
B3B0  嘲 潮 巢 吵 炒 车 扯 撤 掣 彻 澈 郴 臣 辰 尘 晨
B3C0  忱 沉 陈 趁 衬 撑 称 城 橙 成 呈 乘 程 惩 澄 诚
B3D0  承 逞 骋 秤 吃 痴 持 匙 池 迟 弛 驰 耻 齿 侈 尺
B3E0  赤 翅 斥 炽 充 冲 虫 崇 宠 抽 酬 畴 踌 稠 愁 筹
B3F0  仇 绸 瞅 丑 臭 初 出 橱 厨 躇 锄 雏 滁 除 楚

比如上面这个表,这是一个遵循GB2312国标的字符排列表。举个栗子,B3A1是16进制数,这个就代表“场”字、什么意思呢?看看下面的代码。

//主函数打印一个“场”字
LcdPutString(30,30,"场",FontType24,NORMAL);
//LcdPutString函数中解析输入的汉字“场”,汉字是占用两个字节
tempint = (((unsigned int)*str)<<8) + (unsigned int)*(str+1);

我在主函数显示一个汉字“场”, LcdPutString 函数中的*str是个形参,指向“场”在单片机中的位置。将指针分解成十进制,并赋值给tempint。也就是说,tempint 的值就是“场”在单片机中仿真的值、下面试仿真结果。

45985转换成十六进制就是B3A1

通过这个实验,我们可以知道,汉字在计算机中是怎么存储的。本质还是0和1,因为计算机只能识别0和1。另外一点就是每个字符在计算机中都有唯一一个二进制与其对应。

显示函数的实现

取完模之后怎么显示呢?以我最近用的一个例子进行讲解。
  
硬件基础:S08DZ60驱动1.27寸屏幕(驱动SSD1351),汉字模用的字库(GT30L32S4W),基础SPI通信不在讲解,只说下应用函数。代码中有详细注释。

1.首先实现点亮一个点

void Draw_Point(unsigned char x, unsigned char y, int Colour_RGB)
{Write_Command(0x15);  // 设置列地址Write_Data(x);    Write_Command(0x75);  // 设置行地址Write_Data(y);    Set_Write_RAM();  //使能MCU写RAMWrite_Data(Colour_RGB >> 8); //写入填充颜色高字节Write_Data(Colour_RGB);  //写入填充颜色低字节
}

2.以汉字12 * 12,字符6 * 12为例写的驱动函数

void PutDotBytes12(unsigned char x,unsigned char y,unsigned char *DataPtr,unsigned char mode)
{unsigned char i, j; //定义变量unsigned char Var_Temp, x_Temp; //定义变量x_Temp = x; //获取x起始坐标if(IsAsciiType) //字符{for(i = 0; i < 9; i++) //6*12 = 9*8;一次只能写入一字节,也就是8位,所以采用8*32的画法{            Var_Temp = DataPtr[i]; //获取汉字在数组的偏移量for(j = 0; j < 8; j++){if(Var_Temp & 0x80)   //先画最高位的点,为1则画对应的颜色Draw_Point(x, y, 0x55);//else//Draw_Point(x, y, 0x0000); //为0则黑色(都不亮),可作为背景色Var_Temp <<= 1; //移位,准备画下一个点x++;  //x坐标加1if((x - x_Temp) == 6)  //画完一列{x = x_Temp; //x坐标回到起始位置y++;  //y坐标加1break;  //退出当前循环}}}}else{for(i = 0; i < 24; i++) //12*12 = 32*8;一次只能写入一字节,也就是8位,所以采用8*32的画法{            Var_Temp = DataPtr[i]; //获取汉字在数组的偏移量for(j = 0; j < 8; j++){if(Var_Temp & 0x80)   //先画最高位的点,为1则画对应的颜色Draw_Point(x, y, 0x55);//else//Draw_Point(x, y, 0x0000); //为0则黑色(都不亮),可作为背景色Var_Temp <<= 1; //移位,准备画下一个点x++;  //x坐标加1if((x - x_Temp) == 12)  //画完一列{x = x_Temp; //x坐标回到起始位置y++;  //y坐标加1break;  //退出当前循环}}}}}

3.显示函数(集成到一个函数中)

void LcdPutString(unsigned char x,unsigned char y,const char *str,unsigned char type,unsigned char mode)
{unsigned char *dotptr;unsigned int  tempint;while (*str != 0) //判断字符是否为0,不为0,则进入循环中{if ((unsigned char)*str < 0x80)     //根据输入数据的大小判断是字符还是汉字,{IsAsciiType = 1;    //字符tempint = (unsigned int)*str;}else{IsAsciiType = 0;    //汉字tempint = (((unsigned int)*str)<<8) + (unsigned int)*(str+1);}dotptr = (unsigned char *)GetDotAddr(tempint, type); //查找当前字符的点阵字模位置//PutDotBytes(x+LCD_X_SHR, y, dotptr, mode);    //将字模输出至显示设备 //OLED - CT2412864右移2点阵switch(type){case   FontType08:PutDotBytes08(x+LCD_X_SHR, y, dotptr, mode);    //将字模输出至显示设备 //OLED - CT2412864右移2点阵break;case   FontType12:PutDotBytes12(x+LCD_X_SHR, y, dotptr, mode);break;    //将字模输出至显示设备 //OLED - CT2412864右移2点阵 case   FontType16:PutDotBytes16(x+LCD_X_SHR, y, dotptr, mode);    //将字模输出至显示设备 //OLED - CT2412864右移2点阵break;case   FontType24:PutDotBytes24(x+LCD_X_SHR, y, dotptr, mode);    //将字模输出至显示设备 //OLED - CT2412864右移2点阵break;}if (1 == IsAsciiType)               //调整指针至下一个将要显示的字符{str += 1;}else{str += 2;}x += (Xsize+8);                         //调整显示横坐标if ((unsigned char)*str < 0x80){Xsize = Xsize/2;}if ((x + Xsize) > Max_Column){x = 0;if ((y + Ysize) > Max_Row){break;}else{y += Ysize;                 //调整显示纵坐标}}}//End of while
}

如果用取模软件取模,直接修改for循环中的数组 DataPtr[i] 为取模定义的数组即可。

总结

这节主要讲了屏幕的驱动函数怎么写的,还有一篇讲解的IIC协议的,以及还有一节51822驱动0.96寸屏幕的,把这三章结合起来理解就能吃透屏幕啦,其他屏幕基本上都是一样的套路。
因为最近一直在搞屏幕驱动,以前都是调用库函数,或者别人写好的驱动函数,这次开发一款新产品,索性直接把底层也搞了一下,并总结下来,希望能帮到你。

用单片机在屏幕上显示字库中的汉字相关推荐

  1. 计算机游戏中屏幕上显示的,电脑在玩全屏游戏的时候显示屏老是出现无信号

    公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:电脑在玩全屏游戏的时候显示屏老是出现无信号 问题详情:我在玩CF的时候 每次进入游戏 显示屏突然出现无信号 好几次了推荐回答:这样的 ...

  2. 要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布上,这样才可以显示在手机屏幕上。Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设置,主要方法(没有全部列

    要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布上,这样才可以显示在手机屏幕上.Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设置,主要方法(没有全部列 ...

  3. 在 BUF 和 BUF+1、BUF+2 单元分别放有一个无符号字节型数,编程序将其 中最大数存入 MAX 单元,并在屏幕上显示。

    问题描述: 在 BUF 和 BUF+1.BUF+2 单元分别放有一个无符号字节型数,编程序将其 中最大数存入 MAX 单元,并在屏幕上显示. 汇编代码,已调试 DATA SEGMENTBUF DB 7 ...

  4. stm32f103利用HC06进行蓝牙通信,在7针的OLED屏幕上显示,带数据更新功能(带超详细讲解)

    stm32f103利用HC06进行蓝牙通信,在7针的OLED屏幕上显示,带数据更新功能(带超详细讲解) 首先看看效果吧 手机端发送一个数据在OLED屏幕上显示 其实蓝牙通信就是个蓝牙转串口的过程,手机 ...

  5. 计算两个数之间所有整数的和_汇编语言:输入2个0–99之间的整数,对其做乘法运算,在屏幕上显示出该乘积对应的二进制和十六进制数...

    实验要求: (1)在屏幕提示:"please input the first number(0–99): "后,输入一个0–99之间的整数. 若所输入的数不在此范围内,或输入其它字 ...

  6. ABAP屏幕上显示LIST的三种方法

    屏幕上显示LIST的三种方法 在abap开发中,经常有用户提出list的需求,实现的方法很多,通常用的有以下三种总结一下供大家参考: 1:手工添加-就是根据需要把LIST要显示的内容一条一条加到LIS ...

  7. 汇编语言 修改显存 在屏幕上显示图案

    原理 0b810:0000是显存地址,直接修改其中的内容会在屏幕上显示ascii码的对应内容 效果 在最上面一行右边 代码 assume cs:codesgcodesg segmentfishcc: ...

  8. bh1750采集流程图_lcd_bh1750 通过 采集环境光照度,并在野火stm32mini板子的屏幕上显示。 SCM 机开发 272万源代码下载- www.pudn.com...

    文件名称: lcd_bh1750下载  收藏√  [ 5  4  3  2  1 ] 所属分类: SCM 开发工具: Visual C++ 文件大小: 2640 KB 上传时间: 2017-03-12 ...

  9. 十六、在屏幕上显示时间

    上一章中已经实现了在屏幕上显示字符,要在屏幕上显示时间只需要修改主函数即可,主函数修改如下: 1 #include <stdio.h> 2 #include <time.h> ...

最新文章

  1. 地图构建两篇顶级论文解析
  2. linux sed命令处理文本文件
  3. 通俗易懂的讲解区块链
  4. 关于fflush、缓冲区、scanf、EOF等问题真麻烦
  5. YY/T 0664—2020《医疗器械软件 软件生存周期过程》 相关
  6. git 提交修改到github上
  7. .NET Core 服务在 ARM64 服务器中的部署
  8. Python 程序 可以一直输入 quit_从零开始学Python - 第002课:第一个Python程序
  9. 属性值动态调整_【VBA】Range对象的常用方法属性(三)
  10. django-视图中的request对象的属性
  11. 组件化思维对于一个UI设计来说有多重要?
  12. mysql索引方式_MySQL数据库的索引方式
  13. 图片自动生成css,CSS Sprites Generator
  14. 阵列信号处理知识点合集
  15. 高级研发工程师都有哪些特点?快来看看你是否符合【超级准】
  16. FLV在线flash播放器JW PLAYER
  17. 上海伯俊软件科技有限公司面试题
  18. 新项目筹划中。。。。
  19. java计算工作日_Java工作日计算工具类
  20. FFmpeg 命令行和API方式转换rtsp或264成Fragmented MP4

热门文章

  1. 烦人的IE浏览器兼容问题,F12开发模式正常,普通模式就不行
  2. Office project 2016安装
  3. 关于.NET使用Microsoft.Office.Interop.Excel导出“异常来自 HRESULT:0x800A03EC”
  4. linux 执行文件时提示权限不够 chmod 777
  5. 股市基础知识、指标详解、ma均线分析、成交量分析
  6. 共建征集令 | 2023开放原子全球开源峰会分论坛、议题开放征集中
  7. Springboot毕设项目婚车租赁系统的设计与实现hsh20(java+VUE+Mybatis+Maven+Mysql)
  8. java用户删除_添加/删除用户
  9. 走进他人内心的七项修炼
  10. 【亲测】Parallels Desktop 16 / 17在MacOs Big Sur / Monterey下网络初始化失败:您的虚拟机将继续正常运作 解决办法