辅助舍友做毕业设计中的显示部分,优化了OLED的汉字显示,简化了函数的调用方式,略有小得,留做记录。程序在最后面。
未经授权,不得转载!_(:з)∠)_
前言
中景园的给的例程中的汉字显示函数调用方式是这样的:
OLED_ShowCHinese(0,0,0);//中 OLED_ShowCHinese(18,0,1);//景 OLED_ShowCHinese(36,0,2);//园 OLED_ShowCHinese(54,0,3);//电 OLED_ShowCHinese(72,0,4);//子 OLED_ShowCHinese(90,0,5);//科 OLED_ShowCHinese(108,0,6);//技
只听到从知秋君办公室传来知秋君的声音: 方惭不耕者,禄食出闾里。有谁来对上联或下联?
一个字:太呆了!
首先,汉字显示是靠其在字库内的索引位置来得到点阵数据然后显示,索引必须自己去弄,无法直接在程序中直观地看出到底显示了什么汉字;
其次,中文英文显示函数是独立的,要是中英文混显动态长度显示怕不是要折腾死人。
用户体验极差。
为了解决上面临两个问题,笔者优化了汉字字库的结构和汉字显示函数,并实现了中英文混合现实并自动换行。
先来看看调用方式:
此代码由一叶知秋网-知秋君整理OLED_ShowText(0,0,"苍穹1234",1);//中英文混显 sprintf(temparr,"苍穹%d",i); OLED_ShowText(20,4,temparr,0);//动态显示
一、汉字字库
-
为了方便计算机辨认、接收和处理汉字,为每个汉字编一个唯一的代码,这就是汉字编码。
几乎所有的软件中文显示都是用的都是信息交换用汉字编码字符集GB2312(VSC也是可修改为GB2312的),GB2312共收入汉字6763个和非汉字图形字符682个。整个字符集分成94个区,每区有94个位。每个区位上只有一个字符,因此可用所在的区和位来对汉字进行编码,称为区位码。
先介绍一点前置知识:
为了方便查找汉字,我们也将使用到汉字的区位码。
在制作字库之前,先定义一个结构体类型:
typedef struct { char name[3]; char dat[32]; }chinese;
结构体的第一个成员name[3] 用来存放汉字的区码和位码以及一个字符串结束符 ‘\0’ ,这里的 ‘\0’ 并不是必要的。
结构体的第二个成员dat[32] 用来存放汉字点阵数据,这里采用的是16*16的汉字,16*16/8=32,故单个汉字的点阵数据为32字节。
拥有了此结构体类型后,我们就可以开始制作字库了QwQ
首先声明一个结构体数组,长度不用填写
此代码由一叶知秋网-知秋君整理chinese Hzk[]={};
然后用 PCtoLCD2002.exe 软件取字模,
软件设置如下
其他的操作就不谈了,很简单的,要是觉得用的不习惯,改天出个做简单的取字模软件教程哈哈,滑稽
再然后呢,按照如下的组织方式放到字库里面
chinese Hzk[]={ "中", {0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00,0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00}, "景", {0x40,0x40,0x40,0x5F,0x55,0x55,0x55,0x75,0x55,0x55,0x55,0x5F,0x40,0x40,0x40,0x00,0x00,0x40,0x20,0x0F,0x09,0x49,0x89,0x79,0x09,0x09,0x09,0x0F,0x20,0x40,0x00,0x00}, "园", {0x00,0xFE,0x02,0x42,0x4A,0xCA,0x4A,0x4A,0xCA,0x4A,0x4A,0x42,0x02,0xFE,0x00,0x00,0x00,0xFF,0x40,0x50,0x4C,0x43,0x40,0x40,0x4F,0x50,0x50,0x5C,0x40,0xFF,0x00,0x00}, };
顺序是无所谓的。
二、汉字显示函数
/******************************************************************************** * @函数名: OLED_ShowCHineseWord * @函数描述: 在指定位置显示占宽16*16的单个 汉字 * @函数作者: 矛盾聚合体 * @输入参数: 参数名 参数类型 参数描述 @x: u8 列坐标,0~127 @y: u8 行坐标,0~7 @str: u8* 要显示的汉字 @flag: u8 反白标志,非0时反白显示 * @返回值: void * @其他: ********************************************************************************/ void OLED_ShowCHineseWord(u8 x,u8 y,u8* str,u8 flag) { u8 t=0; u16 index; for(index=0; index<sizeof(Hzk)/35; index++) { if(Hzk[index].name[0] == str[0]&&Hzk[index].name[1] == str[1])//对比汉字区码位码 { OLED_Set_Pos(x,y); //设置OLED光标位置 for(t=0; t<16; t++)//先写汉字上半部分数据 { if(flag==0)OLED_WR_Byte(Hzk[index].dat[t],OLED_DATA); else OLED_WR_Byte(~Hzk[index].dat[t],OLED_DATA); } OLED_Set_Pos(x,y+1);//设置OLED光标位置 for(t=0; t<16; t++) //再写汉字下半部分数据 { if(flag==0)OLED_WR_Byte(Hzk[index].dat[t+16],OLED_DATA); else OLED_WR_Byte(~Hzk[index].dat[t+16],OLED_DATA); } } } }
调用方式:
OLED_ShowCHineseWord(0,6,"中",1);// 在6行0列反白(即高亮)显示“中”字
额,代码贴出来好像就没啥好说的了_(:з)∠)_
三、中英文混合显示函数
首先,要对例程给的ASCII字符显示函数做一定的修改:
/******************************************************************************** * @函数名: OLED_ShowChar * @函数描述: 在指定位置显示占宽8*16的单个ASCII字符 * @函数作者: 矛盾聚合体 * @输入参数: 参数名 参数类型 参数描述 @x: u8 列坐标,0~127 @y: u8 行坐标,0~7 @chr: u8 要显示的ASCII字符 @flag: u8 反白标志,非0时反白显示 * @返回值: void * @其他: ********************************************************************************/ void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 flag) { unsigned char c=0,i=0; c=chr-' ';//得到偏移后的值 if(x>Max_Column-1){x=0;y=y+2;} OLED_Set_Pos(x,y); for(i=0;i<8;i++) { if(flag==1)OLED_WR_Byte(~F8X16[c*16+i],OLED_DATA); else OLED_WR_Byte(F8X16[c*16+i],OLED_DATA); } OLED_Set_Pos(x,y+1); for(i=0;i<8;i++) { if(flag==1)OLED_WR_Byte(~F8X16[c*16+i+8],OLED_DATA); else OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA); } }
然后。。。直接上代码吧,尽在不言中
/******************************************************************************** * @函数名: OLED_ShowText * @函数描述: 在指定位置显示中英文字符串 * @函数作者: 矛盾聚合体 * @输入参数: 参数名 参数类型 参数描述 @x: u8 列坐标,0~127 @y: u8 行坐标,0~7 @str: u8* 要显示的字符串 @flag: u8 反白标志,非0时反白显示 * @返回值: void * @其他: ********************************************************************************/ void OLED_ShowText(u8 x,u8 y,u8* str,u8 flag) { u8 tempstr[3] = {'\0'}; while(*str!='\0') { if(*str&0x80) { tempstr[0]=*str++; tempstr[1]=*str++; OLED_ShowCHineseWord(x,y,tempstr,flag); x+=16; if(*str&0x80)//判断下一个字符是中文还是英文 { if(x>=112){y++;y++;x=0;}//修改地址 } else { if(x>=120){y++;y++;x=0;}//修改地址 } } else { OLED_ShowChar(x,y,*str++,flag); x+=8; if(*str&0x80) { if(x>=112){y++;y++;x=0;}//修改地址 } else { if(x>=120){y++;y++;x=0;}//修改地址 } } } }
汉字和ASCII码的最大的区别就是,汉字的区码和位码最高为都是1,而ASCII码最高位为0,依据此,将汉字和ASCII字符区分开来。
为了实现自动换行,这里做了一点小处理,每次写字符后,光标位置移动,并根据下一个字符的类型判断是否换行:
if(*str&0x80) { if(x>=112){y++;y++;x=0;}//修改地址 } else { if(x>=120){y++;y++;x=0;}//修改地址 }
有读者可能就要问了,要是下一个字符是结束符怎么办?你没做处理鸭?
笑话!再到 while可就跳出去了,不会执行到写字符的程序的
那么,这么好的程序在哪里呢?↓←→↖↗↙↘↕
↓
- ←(看见了吗?滑稽)
↑
https://pan.baidu.com/s/1COY6auWgYaIXgAtSb9KsuQ
1ots