**
**
先说结论,不行。
自定义的汉字,每个占4个字模,而LCD1602的CGRAM只允许自定义8个。那么该如何显示3个汉字(12个字模)呢?
我先设置每个汉字的上面一半,也就是6个字模。显示完后,再定义下面一半。
LCD1602自定义字模的指令是01XX XXXX,从0x40到0x7f总共64个字节,8个字模。
字模分别从0x40,0x48,0x50,0x58,0x60,0x68,0x70开始。
#include"reg52.h"
#include"intrins.h"
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
unsigned char code hanzi_nihao[]={
//你
0x00,0x00,0x04,0x0d,0x09,0x18,0x14,0x14, //你 top-left
0x00,0x08,0x10,0x1f,0x91,0x0a,0x08,0x08, //你 top-right
0x04,0x04,0x05,0x04,0x04,0x00,0x00,0x00, //你 bottom-left
0x08,0x1a,0x0b,0x09,0x18,0x00,0x00,0x00, //你 bottom-right
//好
0x00,0x00,0x04,0x08,0x08,0x1f,0x0a,0x0a, //好 top-left
0x0a,0x04,0x0a,0x12,0x00,0x00,0x00,0x00, //好 top-right
0x00,0x00,0x0e,0x02,0x04,0x0f,0x04,0x04, //好 bottom-left
0x04,0x04,0x04,0x14,0x0c,0x04,0x00,0x00 //好 bottom-right
};
unsigned char code hanzi_hushengjian[]={
//工
0x00,0x1F,0x01,0x01,0x01,0x01,0x01,0x01, //工 top-left
0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00, //工 top-right
0x01,0x01,0x01,0x01,0x01,0x01,0x1F,0x00,//工 bottom-left
0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00, //工 bottom-right
//口
0x00,0x00,0x1F,0x10,0x10,0x10,0x10,0x10,//口 top-left
0x00,0x00,0x1F,0x01,0x01,0x01,0x01,0x01, ///口 top-right
0x10,0x10,0x10,0x10,0x10,0x1F,0x00,0x00, ///口 bottom-left
0x01,0x01,0x01,0x01,0x01,0x1F,0x00,0x00,////口 bottom-right
//健
0x01,0x02,0x04,0x0B,0x19,0x09,0x09,0x0B, //健 top-left
0x00,0x08,0x1E,0x0A,0x1F,0x0A,0x1E,0x08, ////健 top-right
0x09,0x09,0x0D,0x0B,0x09,0x09,0x0A,0x0C, /////健 bottom-left
0x1E,0x08,0x1E,0x08,0x08,0x10,0x10,0x0F/////健 bottom-right
};
void delay(int i);
void init();
void wcmd(char _cmd);
void wdata(char _data);
char rdata();
void ifnotbusy();
void set_hanzi();
void set_half_hanzi(int n);
void main(){
while(1){
init();
set_half_hanzi(0);
wcmd(0x80);
wdata(0x00);
wdata(0x01);
wdata(0x02);
wdata(0x03);
wdata(0x04);
wdata(0x05);
init();
set_half_hanzi(1);
wcmd(0xc0);
wdata(0x00);
wdata(0x01);
wdata(0x02);
wdata(0x03);
wdata(0x04);
wdata(0x05);
}
while(1);
}
//自定义汉子字库
void set_hanzi(){
unsigned char j,i=0;//unsigned char is must
for(j=0x40;j<=0x7f;j++,i++){
wcmd(j);
wdata(hanzi_nihao[i]);
}
}
void set_half_hanzi(int n){
unsigned char i,j;
for(j=0x40,i=0+n*16;j<0x50;j++,i++){
wcmd(j);
wdata(hanzi_hushengjian[i]);
}
for(j=0x50,i=32+n*16;j<0x60;j++,i++){
wcmd(j);
wdata(hanzi_hushengjian[i]);
}
for(j=0x60,i=64+n*16;j<0x70;j++,i++){
wcmd(j);
wdata(hanzi_hushengjian[i]);
}
}
void delay(int i){
int j;
while(i--){
for(j=0;j<250;j++){
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
//init LCD and clear screen
void init(){
wcmd(0x38);//8位 双行 5X7点阵
wcmd(0x0c);//开显示 无光标 不闪烁
wcmd(0x06);//右移
wcmd(0x01);//clear screen
}
void wcmd(char _cmd){
ifnotbusy();
LCD_E=0;
LCD_RS=0;//command
LCD_RW=0;//write
delay(1);
P0=_cmd;
delay(1);
LCD_E=1;
delay(1);
LCD_E=0;
delay(1);
}
void wdata(char _data){
ifnotbusy();
LCD_E=0;
LCD_RS=1;//data
LCD_RW=0;//write
delay(1);
P0=_data;
delay(1);
LCD_E=1;
delay(1);
LCD_E=0;
delay(1);
}
char rdata(){
P0=0xff;
LCD_RS=0;//command
LCD_RW=1;//read
LCD_E=1;
delay(1);
LCD_E=0;
delay(1);
return P0;
}
void ifnotbusy(){
P0=0xff;
LCD_RS=0;//command
LCD_RW=1;//read
LCD_E=1;
while((bit)(P0&0x80)){ //BF=0 equal not busy
LCD_E=0;
LCD_E=1;
}
LCD_E=0;
}
这样的话,显示的效果就是上面显示一半,消隐,下面显示一半,消隐,再上面——不能完整地显示3个汉字。
如果把中间的init()删除,那么第一行显示完上面一半后,在第二行,即字的下面一半显示出来前,第一行的显示就会被更改为下面的一半。原因是在设置汉字下面一半的时候把CGRAM内自定义的区域给覆盖了。
所以,最多只能完整显示两个汉字!
LCD本身带有控制器,驱动器和显示器,既然本身不是简单的门芯片,那么借由单片机使用它就必须满足它的一些性质。
每个指令或数据传输给LCD需要等待一定的时间后,LCD才准备好。不单是时间考虑周到,指令的顺序也是关键。
由LCD1602指令表可知,第7条指令是自定义字符的,即01XX XXXX。满足这个条件的地址内可以放入字符。
我上面存放在数组内的每个字符是8位的,而实际是5X8是怎么回事?
通过开始时的初始化。
指令6中(F=0)设置了每个字模显示5X8的点阵。而且,每个8位字符从低位到高位,也就是从右到左——即以右上角为起点,画的一个区域。
如何做5X8的字模?
常用辅助开发软件
链接:https://pan.baidu.com/s/1858SQfYpiBtBVFNYy0ladw 提取码:0act
复制这段内容后打开百度网盘手机App,操作更方便哦
使用其中的文字取模软件,新建8X8点阵后,在其他选项里改为横向取模。在模拟动画里把工作区放大,然后画完后点以C51格式生成就得到8个8位字符(一个字模)了。