OLED上迷你世界彩色闪烁字体体怎么实现

还没有帐号? 赶紧
用户版块帖子
菜鸟关于0.96寸OLED显示单个汉字及多个汉字的那些事
UID:1505079
在线时间322小时
M币6286专家11
最近在玩一个0.96寸OLED屏,这货着实的小,但显示蛮清晰的,虽然啥用途都没有,但因为一上手测试就感觉它的驱动和其他的12864有很大的不同,由此激发了兴趣,我买的是一个7针接口的屏,默认为SPI驱动接口,用店家的程序走了一下,显示一幅图片没啥问题,但总感觉接线太多,于是查看数据手册,按照模块使用说明改造了接口,是他变成了I2C接口的了,电源+数据+时钟4根线搞定,我还画蛇添足的引出了RSE结果真的用不到,无论怎么弄都不能使系统复位(也可能是我不知道复位后的结果),于是接了高电平不理睬他了,用清屏函数足以了,接下来就是按照自己的想法改编程序了,首先实验的是显示一个点,而后是一条线,最后是显示一个汉字,至于显示点、线啥的只是一试了之,下面重点说说显示汉字的函数与原理,这是一个由简单完成到复杂学习的过程,也有以前擦肩而过不求甚解的知识再次深入的了解了一些,而达到成功,用到的绝非编程高手明明白白的处理方法,而是用了很外行的方法,没有系统学习过编程知识的菜鸟,对于编程中遇到了问题,那种大脑空白的感觉是内行人感觉不到的,条条大路通罗马,办法总比困难多,只要能够解决问题,心里总会乐呵的,分享于此,高手见了如果想笑就请大声的笑,新手见了如果觉得有用就详细看一下,闲话少说书归正传。 一、最简单的汉字显示方法和函数先用取字模软件生成汉字的字模数据,做成数组如下:uchar code hanzi[]={0x60,0x66,0x66,0xFE,0xFE,0x63,0x63,0x60,0xFC,0xFC,0x0C,0x0C,0xFC,0xFC,0x00,0x00,0x0C,0x06,0x03,0x7F,0x7F,0x01,0x03,0x02,0x1F,0x1F,0x0C,0x0C,0x1F,0x1F,0x00,0x00,//和};而后是汉字显示函数如下:1、屏上位置确定函数,这是很多资料里都有的,void display_xy(uchar x, uchar y){Write_IIC_Command(0xb0+x);Write_IIC_Command(((y&0xf0)&&4)|0x10);Write_IIC_Command((y&0x0f)|0x01); }2、汉字显示函数,这是经过我改编的//--------16*16汉字显示函数----------------void hanzi_16(uchar x,uchar y,uchar code *s){uchar i,j;x=x*2;//每个字占用两页地址y=y*16;//每16列一个字for(j=0;j&2;j++) //页计数{display_xy(x+j,y);for(i=0;i&16;i++){Write_IIC_Data(*s++); //一页汉字数据输出}}}//--------主函数--------------------------void main(void){Initial_SSD1306();Delay_1ms(5);CLS_OLED();while(1){hanzi_16(0,0,hanzi);//显示输入}}以上程序执行后,会在屏的左上角显示一个“和”字。二、多个汉字的显示(问题来了)如果用上述方法显示多个汉字,需要一个一个的输出,想想都头大,于是想到了汉字字符串输出的方法,于是想到了结构体数组,于是就有了如下的代码:1、结构体数组:// ------------------&&汉字字模的数据结构定义 ------------------------ //struct&&typFNT_GB16&&&&&&&&&&&&&&&& // 汉字字模数据结构 {unsigned char&&Index[3];&&&&&&&&&&&&&& // 汉字内码索引 unsigned char&& Msk[32];&&&&&&&&&&&&&&&&&&&&&&&&// 点阵码数据 };/////////////////////////////////////////////////////////////////////////&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // 汉字库: 宋体16.dot,列行式,逆向 /////////////////////////////////////////////////////////////////////////code struct&&typFNT_GB16 codeGB_16[] =&&&&&&&&&&// 数据表 {&日&,0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,&照&,0x00,0x00,0xFE,0x22,0x22,0xFE,0x40,0x21,0xD1,0x4F,0x41,0x51,0x61,0xDF,0x00,0x00,0x40,0x60,0x3B,0x01,0x09,0x33,0x60,0x00,0x0F,0x32,0x62,0x02,0x0A,0x37,0x60,0x00,&香&,0x08,0x08,0x8A,0x8A,0x4A,0x2A,0x1A,0xFF,0x19,0x29,0x49,0x49,0x88,0x88,0x88,0x00,0x01,0x01,0x00,0x00,0x7F,0x49,0x49,0x49,0x49,0x49,0x49,0x7F,0x00,0x01,0x00,0x00,&庐&,0x80,0x60,0x00,0xFF,0x20,0x18,0x00,0xF8,0x88,0x89,0x8E,0x88,0x88,0xFC,0x08,0x00,0x40,0x20,0x18,0x07,0x84,0x48,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,};2、还是显示一个汉字,函数如下://=======写一个16*16汉字(结构体字库模式)===================================void PutGB1616(uchar x, uchar&&y, uchar c[2]){uchar a,k,i,j; //一些计数变量uchar z=0;&&//用于一个汉字数据的计数变量uchar z0,z1;//设两个侦测变量z0=c[0];//暂存字符区码用于查看z1=c[1];//暂存字符位码用于查看x=x*2;y=y*16;for(k=0;k&30;k++)&&//查找汉字位置{if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1])){for(i=0;i&32;i++) //读出一个汉字的数据{zimo=codeGB_16[k].Msk;//将汉字数据存入显示缓存区}}}for(a=0;a&2;a++)&&//分两页写入OLED{display_xy(x+a,y);for(j=0;j&16;j++) //每页16列数据{Write_IIC_Data(zimo[z]);//写0-32个汉字显示数据z++;&&//32个数据连续计数}}}这个函数也不是啥新鲜的东西,网上很多的,但是,因为此屏每一个16*16的汉字要写到两页地址里,所以就和其他连续地址的12864不同了,为了解决这个问题,我用了一个很笨的方法,就是先定义一个数组,我称他为显示缓存区:uchar zimo[32];它可以储存32个数据,这里需要注意的是,不能将他设置到code区域,否则是不能装填数据的,小小的浪费一点内存(真的很少)会使输出函数简单许多,其他就不多啰嗦了。依此,主循环里这样调用就可以显示一个汉字了,当然了,数组里一定要有你欲显示的那个汉字以及对于的数组数据,while(1){PutGB,&照&);}}三、重点来了,有了显示一个字符的函数,显示字符串还难吗,对于其他12864屏真的不难,而对于这个OLED却挺不顺利的,首先还是应用网上大家常用的方法,函数如下:void OLED_PutString(uchar x,uchar y,uchar *s) {//y水平方向起始位置//x垂直方向起始位置while(*s)//循环提取字符直到结束符\0出现{PutGB1616(x,y,s);//字符显示输出s++;//提取下一个字符}}主循环中对函数调用的方法如下:while(1){OLED_PutString(3,0,&日照香庐&);}}这个用了无数次的好用的代码,在这里却失效了,竟然显示了一行“日照照照香香庐庐”,此情此景直接懵掉了,这个功能函数因为从未有问题,所以一直在用但真的没细究过运行原理,于是开始了全面的反思,首先想知道的是&日照香庐&这个字符串在函数调用过程中是以怎样的数据形式传递的?于是百度,于是众说纷纭无法核实,无奈之际想到了串口助手,短接了RXD/TXD口于是有了下图:接下来查看国标字库:日字果真是C8D5,原来,他是以国标的形式传递运行的,由此,也就充分理解了那个天书一样的算法的真实含义了,一直在用但从未细究的一个判断式如下:if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1])) //在自建字库中比对查找待用的汉字这个判断式之中,那个c[0]和codeGB_16[k].Index[0]的比较就是查对汉字的区码,而c[1]和codeGB_16[k].Index[1]比较就是查对汉字的位码了解到这些后,就想出了一个歪点子,于是,在字符输出函数中添加了两个变量z0,z1(详见上述函数),封闭掉无关的函数而后编译程序后,进入了调试界面,逐次单步运行程序,并记录数据,方法如下图: 经过8次循环后跳出,得到了下面的数据:[C8D5]--D5D5--[D5D5]--D5CF--[CFE3]--E3C2--[C2AE]--AE00--跳出,这个结果揭示了两个问题,其一是第一个数据是正确的,接下来的数据每间隔一个数据出现一个正确的数据,其二是字符串输出原本就是每个字符两个字节,四个汉字8个字节最后一个是结束符\0由此产生00--跳出的结果。发现了问题就找到了解决问题的方法,非常的简单只要将函数中的s++改成s+=2;就完全ok了。while(*s){PutGB1616(x,y,s);s+=2;y++;}}最后看看显示汉字的效果并全部程序: 以下是程序,直接贴这里供新手试用吧,还是老办法,复杂粘贴就可以直接用了,如有问题欢迎探讨交流,本资料仅供学习之用,请勿用于商业用途。以下是main.c#include &STC12C5A60S2.h&#include &intrins.h&//---------------------------------------------#define uint&&unsigned int&&&&&& #define uchar unsigned char//--------------图片数据表--------------------#include &OLED_I2C.h&#include &init_OLED.h&#include &BMP.h&#include &16hanzi.h&//--------------------------------------------sbit RES=P1^2;uchar zimo[32];//设置显示数据缓存区//--------------------------------------------void Delay_1ms(uint n)&&//n*1ms@12.000MHz{uchar i,while(n--){_nop_();_nop_();i = 12;j = 168;do{while (--j);} while (--i);}}//-----清屏函数-----------------------void CLS_OLED(){&&uchar x,y;&&uint i=0;&&for(y=0;y&8;y++)&&&&{&&&&&&Write_IIC_Command(0xb0+y);&&&&&&Write_IIC_Command(0x00);&&&&&&Write_IIC_Command(0x10);&&&&&&for(x=0;x&128;x++)&&&&&&&&{&&&&&&&&&&Write_IIC_Data(0);&&&&&&&&}&&&&}}//----------图片显示函数--------------------/*void Picture_display(){&&uchar x,y;&&uint i=0;&&for(y=0;y&8;y++)&&&&{&&&&&&Write_IIC_Command(0xb0+y);&&&&&&Write_IIC_Command(0x00);&&&&&&Write_IIC_Command(0x10);&&&&&&for(x=0;x&128;x++)&&&&&&&&{&&&&&&&&&&Write_IIC_Data(show1[i++]);&&&&&&&&}&&&&}}*///--------字符显示位置坐标函数----------------//--x=行:上--&下共8行、起点0xb0终点0xb8//--y=列:左--&右共128列、起点0x00终点0x10void display_xy(uchar x, uchar y){Write_IIC_Command(0xb0+x);Write_IIC_Command(((y&0xf0)&&4)|0x10);Write_IIC_Command((y&0x0f)|0x01); }//=======写一个16*16汉字(结构体字库模式)===================================void PutGB1616(uchar x, uchar&&y, uchar c[2]){uchar a,k,i,j; //一些计数变量uchar z=0;&&//用于一个汉字数据的计数变量x=x*2;y=y*16;for(k=0;k&30;k++)&&//查找汉字位置{if ((codeGB_16[k].Index[0]==c[0])&&(codeGB_16[k].Index[1]==c[1])) { for(i=0;i&32;i++) //读出一个汉字的数据&&{&&zimo=codeGB_16[k].M//将汉字数据存入显示缓存区&&} }}for(a=0;a&2;a++)&&//分两页写入OLED{display_xy(x+a,y);for(j=0;j&16;j++) //每页16列数据 { Write_IIC_Data(zimo[z]);//写0-32个汉字显示数据 z++;&&//32个数据连续计数 }}}//-------写多个16*16汉字----------------------void OLED_PutString(uchar x,uchar y,uchar *s) {//x垂直方向起始位置//y水平方向起始位置while(*s){PutGB1616(x,y,s);s+=2;y++;}}//--------------------------------------------void main(void){Initial_SSD1306();Delay_1ms(5);RES=1;CLS_OLED();while(1){//PutGB,&照&);OLED_PutString(0,0,&日照香庐生紫烟,&);OLED_PutString(1,0,&遥看瀑布挂前川。&);OLED_PutString(2,0,&飞流直下三千尺,&);OLED_PutString(3,0,&疑是银河落九天。&);}}以下是相关模块代码OLED初始化模块:init_OLED.c////////////////////////////////////////// #include &init_OLED.h&#include &OLED_I2C.h&//------SSD1306应用寄存器设置(初始化)函数---------------void Initial_SSD1306(){Write_IIC_Command(0xAE);//关闭显示Write_IIC_Command(0x20);//设置存储器寻址模式 Write_IIC_Command(0x10);//00,水平寻址;01,垂直寻址;10,寻址模式复位;11,无效Write_IIC_Command(0xb0);//设置页(行)起始地址,0-7行(页)Write_IIC_Command(0xc8);//设置COM输出扫描方向Write_IIC_Command(0x00);//设置列地址低位Write_IIC_Command(0x10);//设置列地址高位Write_IIC_Command(0x40);//设置列起始地址Write_IIC_Command(0x81);//设置对比度控制寄存器Write_IIC_Command(0x7f);Write_IIC_Command(0xa1);//将片段重新映射为0到127Write_IIC_Command(0xa6);//设置正常显示(正常/反向设置)Write_IIC_Command(0xa8);//设置复用率(1到64)Write_IIC_Command(0x3F);//Write_IIC_Command(0xa4);//0xa4,输出跟随RAM内容;0xa5,输出忽略RAM内容Write_IIC_Command(0xd3);//设置显示偏移Write_IIC_Command(0x00);//没有抵消Write_IIC_Command(0xd5);//设置显示时钟分频比/振荡器频率Write_IIC_Command(0xf0);//设置分频比Write_IIC_Command(0xd9);//设置预充电期Write_IIC_Command(0x22); //Write_IIC_Command(0xda);//设置com引脚硬件配置Write_IIC_Command(0x12);Write_IIC_Command(0xdb);//设置 vcomhWrite_IIC_Command(0x20);//0x20,0.77xVccWrite_IIC_Command(0x8d);Write_IIC_Command(0x14);//Write_IIC_Command(0xaf);//开启OLED面板显示 }//=======================================init_OLED.h////////////////////////////////////////////////////////// #ifndef __INIT_OLED_H__#define __INIT_OLED_H__//-SSD1306应用寄存器设置(初始化)函数--void Initial_SSD1306();#endif//==============================================OLED_I2C.c////////////////////////////////////////// #include &OLED_I2C.h&void Delay_us()//1us@12.000MHz{_nop_();_nop_();}//---------I2C总线开启函数-----------------------------void IIC_Start(){&& SCL =&& Delay_us();&&&& SDA =&& Delay_us();&& SDA =&& Delay_us();&& SCL =&& Delay_us();}//--------I2C总线关闭函数------------------------------void IIC_Stop(){&& SCL =&& Delay_us();&& SDA =&& Delay_us();&& SCL =&& Delay_us();&& SDA =&& Delay_us();}//--------I2C写一个字节函数---------------------------void Write_IIC_Byte(uchar IIC_Byte){ for(i=0;i&8;i++)&& {&&if(IIC_Byte & 0x80)&&SDA=&&else&&SDA=&&Delay_us();&&SCL=&&Delay_us();&&SCL=&&Delay_us();&&IIC_Byte&&=1; } SDA=1; Delay_us(); SCL=1; Delay_us(); SCL=0;}//----------I2C写指令函数-------------------------------------void Write_IIC_Command(uchar IIC_Command){&& IIC_Start();&& Write_IIC_Byte(0x78); //DC=0(SA0=0)器件地址0x78&& Write_IIC_Byte(0x00); //写指令&& Write_IIC_Byte(IIC_Command); && IIC_Stop();}//---------I2C写数据函数-------------------------------------------void Write_IIC_Data(uchar IIC_Data){&& IIC_Start();&& Write_IIC_Byte(0x78);&& && Write_IIC_Byte(0x40); //写数据&&&& Write_IIC_Byte(IIC_Data);&& IIC_Stop();}//================================OLED_I2C.h//////////////////////////////////////////////////// #ifndef __OLED_I2C_H__#define __OLED_I2C_H__#include &STC12C5A60S2.h&#include &intrins.h&//-------------------------#define uint&&unsigned int&&&&&& #define uchar unsigned char//-------------------------#define high 1#define low 0 //-------------------------sbit SCL=P1^0;//D0sbit SDA=P1^1;//D1//=======================================void Delay_us();//1us@12.000MHz//---------I2C总线开启函数---------------void IIC_Start();//--------I2C总线关闭函数----------------void IIC_Stop();//--------I2C写一个字节函数--------------void Write_IIC_Byte(uchar IIC_Byte);//----------I2C写指令函数----------------void Write_IIC_Command(uchar IIC_Command);//---------I2C写数据函数-----------------void Write_IIC_Data(uchar IIC_Data);#endif//================================== // ------------------&&汉字字模的数据结构定义 ------------------------ //struct&&typFNT_GB16&&&&&&&&&&&&&&&& // 汉字字模数据结构 {&&&&&& unsigned char&&Index[3];&&&&&&&&&&&&&& // 汉字内码索引 &&&&&& unsigned char&& Msk[32];&&&&&&&&&&&&&&&&&&&&&&&&// 点阵码数据 };/////////////////////////////////////////////////////////////////////////// 汉字字模表&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//// 汉字库: 宋体16.dot,列行式,逆向 //======阴码、顺向、逐行=========//&&&&&&&&///////////////////////////////////////////////////////////////////////// code struct&&typFNT_GB16 codeGB_16[] =&&&&&&&&&&// 数据表 {*******};具体内容请自己取模填写,需要注意的是数组起始第一个数据是汉字字符,要先在英文键盘下输入双引号和逗号,而后在引号中填入汉字或符号,而后接着的是数组数据,详见上文相关。例如:&日&,0x00,0x00,0x00,**********。函数调用时也是先打引号后填字,以免出现空格啥的。说在最后的一句话:工程编译后,请记得将上述的各个.c文件添加到工程里,否则编译器会提示你好多莫名其妙的错误和警告的。**********END**********************
[ 此帖被慕名而来在 09:57重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请
后查看;或者
成为会员获得更多权限
UID:1927788
在线时间2373小时
M币3545专家1
谢谢分享,学习了,我的也是spi的,正在研究显示一个点,哈哈
UID:1138738
在线时间1305小时
M币7649专家3
谢谢分享,我还没玩过OLED屏。虽然有屏,但太小了。大的屏很……还有想问:OLED会有“”烧屏“现象对吧?”
UID:1505079
在线时间322小时
M币6286专家11
回 shanfei_ts 的帖子
:谢谢分享,学习了,我的也是spi的,正在研究显示一个点,哈哈 我的屏被我改成了I2C接口,4根线就可以了,想要显示一个“点”的话,就先调用屏显位置函数再调用数据输出函数,给出位置、送人数据即可。void display_xy(uchar x, uchar y){Write_IIC_Command(0xb0+x);Write_IIC_Command(((y&0xf0)&&4)|0x10);Write_IIC_Command((y&0x0f)|0x01); }主循环中:display_xy(3,5);Write_IIC_Data(0x01);//写数据函数循环执行后就会在第三页的第一行,也就是从上侧第0行起始的第16行以及0起始左向右第四位置显示一个“点”,我只是试了一下没有过深研究,你玩一下看看吧。
UID:1505079
在线时间322小时
M币6286专家11
回 fsss007 的帖子
:谢谢分享,我还没玩过OLED屏。虽然有屏,但太小了。大的屏很……还有想问:OLED会有“”烧屏“现象对吧?”&( 12:25)&也听坛里的老司机说过这个问题,但因为我只是简单的做些实验,还没想出适合的用途,所以也没啥经验。
UID:1795013
在线时间4201小时
M币9003专家274
感谢分享,学习了
UID:1505079
在线时间322小时
M币6286专家11
:感谢分享,学习了 ( 19:41) 多谢打赏鼓励,考虑到最近回赏的一些意外问题,就容后回报吧,欢迎继续交流。
UID:1463162
在线时间699小时
M币3334专家15
这个不错,一般都是直接给字符数组,这个直接给字符。相比IIC,我更喜欢SPI,简单。
UID:2279310
在线时间0小时
M币477专家0
请问楼主可以百度分享工程文件吗?在这里直接复制来用会出现注释乱码,我是新手,真的好头疼啊,谢谢楼主大神了
UID:505102
在线时间967小时
M币297专家6
赵香炉真可怜 歪楼了
访问内容超出本站范围,不能确定是否安全
“新手上路”发帖需审核后才能显示(请认真发帖),达到数码9级后取消此限制
您目前还是游客,请
&回复后跳转到最后一页
Code by , Time now is:07-16 04:44, Total 0.183420(s) query 13,
Gzip enabled&在OLED屏上显示汉字、字符、图片 - 人民币的幻想的日志 -
电子工程世界-论坛
请完成以下验证码
在OLED屏上显示汉字、字符、图片
已有 4019 次阅读 16:26
|个人分类:
最近几天在DIY MP3播放器这个东西,说来其实很简单,去年就做好了。只不过当初是通过1602液晶显示一些简单的东西,歌曲名字还有很多相关信息没法显示。言归正传,这回打算用OLED屏试试看,经实践,显示效果帮帮哒~~。首先先说一下所用方案:MCU用的STM32F103RBT6,OLED用的SSD1306控制的,MCU和屏是通过硬件SPI通信的。具体底层实现请看我曾经发过的一篇帖子。SD卡采用硬件SPI+DMA方式驱动,底层驱动移植自振南的SD卡驱动。字符和数字显示很简单,用的取模软件直接取得,毕竟数量不多,占用体积也不大,相对128K的ROM来说够了。我是用的PCtoLCD2002完美版取得模,点阵采样阴码-列行式-逆向-C51格式。当然还可以自己选择自己喜欢字体大小和格式,就不再多说了。显示原理是这样的:假设以8*8大小某字符为例,占用8*8=64个bits,占用64/8=8Bytes,其他格式请自己推算,列行式即先扫一列在扫下一列,扫完这一行再扫下一行(假设有的话)。至于为什么选择阴码,我用的OLED屏手册上有这样一句话 Display Mode: Passive Matrix,即共阴点阵。大家应该都用过数码管,有共阴和共阳之分,此处原理相同。逆向是低位在前高位在后,即先取低位再取高位。取模原理大致就是这样。显示是某些像素点的显示与不显示,我们把一个字符的8个字节依次取出,通过SPI送屏显示,这样,一个字符就得到显示。图片显示同字符显示,如果想显示到LCD屏上,就需要一些办法了,首先用画图板打开某张图片,然后调整分辨率为水平128,垂直64。并且保存为单色位图格式。然后用PCtoLCD软件打开图片,然后生成字模就好了。以下同字符显示。至于汉字显示就比较复杂,为什么复杂,拿常见的16*16点阵大小的汉字举例,一个汉字占用256bits=32Bytes,想制作MP3,那么长名文件名显示是绕不开的,因此汉字规模按8000算,共占用000Bytes=250.98KB,以单片机的存储空间是放不下的,即使换用更大存储空间的单片机比如1M flashROM,那么24*24点阵的汉字占用562.5KB空间,再加上GBKUNI互转表,那么可供利用的ROM空间就很小了。所以把这些点阵放到一个空间很大又不贵的存储介质中去,不失为一个很好的办法,基于此,我用的SD卡存放这几个文件,分别是12字体,16字体,24字体,GBK转UNI互转表,UNI转GBK互转表。这些是显示汉字及长名所必须的文件。存储的问题解决了,那么怎么找到哪个汉字对应哪些字节的点阵数据呢?这就要稍微了解一下汉字在计算机内表示的知识了,我们知道,由于直接存放点阵太大,所以在计算机内部是利用区位码来存放汉字的,关于这个区位码,我们国家发布了一些标准,当然,在MP3播放器中用到的是简体中文,而且可能出现一些不太常见的汉字,因此我利用GBK标准达到了显示这些汉字的效果。每个GBK码由2个字节组成,第一个字节为0X81~0XFE,第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE。其中与GB2312相同的区域,字完全相同。我们把第一个字节代表的意义称为区,那么GBK里面总共有126个区(0XFE-0X81+1),每个区内有190个汉字(0XFE-0X80+0X7E-0X40+2),总共就有126*190=23940个汉字。我们的点阵库只要按照这个编码规则从0X8140开始,逐一建立,每个区的点阵大小为每个汉字所用的字节数*190。这样,我们就可以得到在这个字库里面定位汉字的方法: 当GBKL&0X7F时:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size); 当GBKL&0X80时:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size); 其中GBKH、GBKL分别代表GBK的第一个字节和第二个字节(也就是高位和低位),size代表一个汉字点阵规模大小,Hp则为对应汉字点阵数据在字库里面的起始地址(假设是从0开始存放)。这样我们只要得到了汉字的GBK码,就可以显示这个汉字了。从而实现汉字在液晶上的显示。说到底,我们知道汉字点阵在哪放,怎么找到某个汉字对应偏移,那么怎么读取数据送到屏幕来呢,接下来就需要一些文件系统的知识了。。。。。。(省略1w字)。当然,也可以不用去了解,用现成的文件系统数据读取函数直接去定位文件位置,读取相应大小数据就好了。这里我用的是znFAT V11.21,实践看来,用起来很不错,移植到你的CPU平台也很简单。这样,就得到显示一个汉字到OLED屏的效果了,为了显示一个汉字,我们不得不去了解文件系统,了解字库中汉字表示,计算偏移量,定位数据,读取数据,处理,送显示。这里就完成了整个汉字、字符、图片的显示原理及实践,在腊月二十九终于做好了,等待回学校有网时发出。以下附上参考资料若干,有愿意一起折腾的朋友可以参考帮助改进,一起努力学习。STM32开发指南V1.0库函数版本。(汉字显示章节)SSD1306数据手册。嵌入式FAT32文件系统设计与实现-基于振南znFAT(上册)。
作者的其他最新日志
评论 ( 个评论)
EEWORLD 官方微信
Powered bystm32,用OLED显示汉字,怎么把字库放在内部flash并显示_百度知道
stm32,用OLED显示汉字,怎么把字库放在内部flash并显示
我有更好的答案
用取模工具提取需要的汉字,做成数组,剩下的就好办了吧?
如果是上位机,发送汉字,单片机接收并显示,那是不是要把整个字库GB2312给提取出来做成数组呀,这么多汉字,怎么个查询呢?
如果是这样,就不用提取字模了。你在网上下载一个HZK16的汉字字库文件,然后根据汉字的区位码计算字模在HZK16中的偏移,然后依次提取32字节的数据发送给单片机。或者是让单片机本身保存一个HZK16字库,这样上位机只需要发送2个字节的汉字区位码,让单片机自己找字模。
为您推荐:
其他类似问题
oled的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 手机字体软件 的文章

 

随机推荐