C51: LCD1602如何显示3个汉字?

**

结论

**
先说结论,不行。
自定义的汉字,每个占4个字模,而LCD1602的CGRAM只允许自定义8个。那么该如何显示3个汉字(12个字模)呢?

我先设置每个汉字的上面一半,也就是6个字模。显示完后,再定义下面一半。

LCD1602自定义字模的指令是01XX XXXX,从0x40到0x7f总共64个字节,8个字模。
字模分别从0x40,0x48,0x50,0x58,0x60,0x68,0x70开始。
C51: LCD1602如何显示3个汉字?_第1张图片

#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需要等待一定的时间后,LCD才准备好。不单是时间考虑周到,指令的顺序也是关键。

C51: LCD1602如何显示3个汉字?_第2张图片

LCD1602指令表

C51: LCD1602如何显示3个汉字?_第3张图片

  1. 清显示,光标复位到00H位置(显示数据存储器DDRAM中)
  2. 光标复位到00H位置
  3. I/D:光标移动方向,高电平左移,低电平右移。S:屏幕上所有文字是否移动,高电平是,低电平否
  4. D:控制整体显示的开与关,高电平是开显示,低电平是关。C:控制光标的开与关,高电平开,低电平关。B:控制光标是否闪烁,高电平闪烁,低电平否。
  5. S/C:高电平移动文字,低电平移动光标
  6. DL:高电平8位总线,低电平4位总线。N:高电平双行,低电平单行显示。F:高电平5X10点阵,低电平5X7点阵。
  7. CGRAM自定义字模存放地址设置
  8. DDRAM地址设置,即屏幕上的显示位置
  9. BF:忙。低电平表示不忙,可以接受指令或数据。

LCD自定义汉字

由LCD1602指令表可知,第7条指令是自定义字符的,即01XX XXXX。满足这个条件的地址内可以放入字符。

我上面存放在数组内的每个字符是8位的,而实际是5X8是怎么回事?
通过开始时的初始化。
指令6中(F=0)设置了每个字模显示5X8的点阵。而且,每个8位字符从低位到高位,也就是从右到左——即以右上角为起点,画的一个区域。
C51: LCD1602如何显示3个汉字?_第4张图片

如何做5X8的字模?

常用辅助开发软件
链接:https://pan.baidu.com/s/1858SQfYpiBtBVFNYy0ladw 提取码:0act
复制这段内容后打开百度网盘手机App,操作更方便哦

使用其中的文字取模软件,新建8X8点阵后,在其他选项里改为横向取模。在模拟动画里把工作区放大,然后画完后点以C51格式生成就得到8个8位字符(一个字模)了。

LCD1602仿真图接法

C51: LCD1602如何显示3个汉字?_第5张图片

你可能感兴趣的:(单片机)