LCD1602已很普遍了,具体介绍我就不多说了,市面上字符液晶绝大多数是基于HD44780液晶芯片的,控制原理是完全相同的,因此HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。字符型LCD通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样,定义如下表所示: 字符型LCD的引脚定义 ![]()
DDRAM就是显示数据RAM,用来寄存待显示的字符代码。共80个字节,其地址和屏幕的对应关系如下表: ![]()
![]() 我们知道文本文件中每一个字符都是用一个字节的代码记录的。一个汉字是用两个字节的代码记录。在PC上我们只要打开文本文件就能在屏幕上看到对应的字符是因为在操作系统里和BIOS里都固化有字符字模。什么是字模?就代表了是在点阵屏幕上点亮和熄灭的信息数据。例如“A” 字的字模:
![]() 从上图可以看出,“A”字的对应上面高位代码为0100,对应左边低位代码为0001,合起来就是01000001,也就是41H。可见它的代码与我们PC中的字符代码是基本一致的。因此我们在向DDRAM写C51字符代码程序时甚至可以直接用P1='A'这样的方法。PC在编译时就把“A”先转为41H代码了。字符代码0x00~0x0F为用户自定义的字符图形RAM(对于5X8点阵的字符,可以存放8组,5X10点阵的字符,存放4组),就是CGRAM了。后面我会详细说的。
那么如何对DDRAM的内容和地址进行具体操作呢,下面先说说HD44780的指令集及其设置说明,请浏览该指令集,并找出对DDRAM的内容和地址进行操作的指令。 共11条指令: 1.清屏指令 ![]()
2.光标归位指令 ![]() 功能:<1> 把光标撤回到显示器的左上方;
![]() 功能:设定每次定入1位数据后光标的移位方向,并且设定每次写入的一个字符是否移动。参数设定的
![]() 功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下:
![]() 功能:使光标移位或使整个显示屏幕移位。参数设定的情况如下:
![]() 功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:
![]() 功能:设定下一个要存入数据的CGRAM的地址。
功能:设定下一个要存入数据的CGRAM的地址。
![]() 功能:<1> 读取忙碌信号BF的内容,BF=1表示液晶显示器忙,暂时无法接收单片机送来的数据或指令;
![]() 功能:<1> 将字符码写入DDRAM,以使液晶显示屏显示出相对应的字符; 11.从CGRAM或DDRAM读出数据的指令一览 ![]() 功能:读取DDRAM或CGRAM中的内容。
读状态 输入:RS=L,RW=H,E=H 输出:DB0~DB7=状态字 看了那么多是不是有些晕?我也是啊,不过慢慢理解还是没问题的。实际上面说了那么多具体怎么操作我还是没会啊?好!咱就简单点。举个实例,就在LCD1602屏幕上第一行第一列显示个“A”字。
/******定义函数****************/ # define uchar unsigned char } //*********主函数***************** //******************************* <版面有长度限制,见下一期>。。。 |
具体电路的制作是很简单的,就接了两个电阻,一个是10欧姆的背光限流电阻,另一个是2K的LCD极板电压调节电阻。这两个电阻的阻值怎么定呢?背光比较简单,它就相当于在后面接了几个发光二极管,任何时候你只要在15、16脚串上个100欧的电位器接上电源,调节电位器,觉得亮度合适。此时的阻值便可。LCD液晶极板驱动电压调节电阻的确定就稍微麻烦一点。在各数据线,控制线接好关通上电源的前提下在第3脚(VEE)和地之间接一个10K的电位器。调节电位器。当3脚电压高时为全亮,电压为0时为全暗(液晶全显示为黑块)。你用电位器把屏幕从全暗刚好调到变亮。这时便可调试程序。待屏幕能正确显示后再细调电位器,使对比度合适。这时的阻值便可确定,然后换成等值的固定电阻焊上便可。
我们接着上次的系统板制做:
![](https://i-blog.csdnimg.cn/blog_migrate/0d39cb18da2a619967a8e4ded5a1e311.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/ef25227a26e08c28df0ff9c546ff77e5.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/26c2fd4119e95c6bd6de9c0903da96df.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/a69ec814023b0ce0f7e660047c79293e.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/b8340b36a2b4dce6e7c8759e2c1436f7.bmp)
![](https://i-blog.csdnimg.cn/blog_migrate/86bc3e7f70322fa1941a133a147a93e6.jpeg)
我们从CGROM表上可以看到,在表的最左边是一列可以允许用户自定义的CGRAM,从上往下看着是16个,实际只有8个字节可用。它的字符码是00000000-00000111这8个地址,表的下面还有8个字节,但因为这个CGRAM的字符码规定0-2位为地址,3位无效,4-7全为零。因此CGRAM的字符码只有最后三位能用也就是8个字节了。等效为0000X111,X为无效位,最后三位为000-111共8个。
如果我们要想显示这8个用户自定义的字符,操作方法和显示CGROM的一样,先设置DDRAM位置,再向DDRAM写入字符码,例如“A”就是41H。现在我们要显示CGRAM的第一个自定义字符,就向DDRAM写入00000000B(00H),如果要显示第8个就写入00000111(08H),简单吧!
好!现在我们来看怎么向这八个自定义字符写入字模。有个设置CGRAM地址的指令大家还记得吗?赶快再找出来看看。
![](https://i-blog.csdnimg.cn/blog_migrate/bc27f63243fa18d8a39f020e10c67b97.jpeg)
从这个指令可以看出指令数据的高2位已固定是01,只有后面的6位是地址数据,而这6位中的高3位就表示这八个自定义字符,最后的3位就是字模数据的八个地址了。例如第一个自定义字符的字模地址为01000000-01000111八个地址。我们向这8个字节写入字模数据,让它能显示出“℃”
地址:01000000 数据:00010000 图示:○○○■○○○○
01000001 00000110 ○○○○○■■○
01000010 00001001 ○○○○■○○■
01000011 00001000 ○○○○■○○○
01000100 00001000 ○○○○■○○○
01000101 00001001 ○○○○■○○■
01000110 00000110 ○○○○○■■○
01000111 00000000 ○○○○○○○○
下面我们写一段程序让这8个自定义字符显示出一个心的图案:
# include <reg51.h>
unsigned char table1[]={0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,
0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00};//心图案
unsigned char table[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//字符℃
sbit LCD1602_RS=P3^0;
sbit LCD1602_RW=P3^1;
sbit LCD1602_EN=P3^2;
void LCD_write_command(unsigned char command);//写入指令函数
void LCD_write_dat(unsigned char dat);//写入数据函数
void LCD_set_xy( unsigned char x, unsigned char y );//设置显示位置函数
void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat);//显示一个字符函数
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//显示字符串函数
void LCD_init(void);//初始化函数
void delay_nms(unsigned int n);//延时函数
/********************************************/
void LCD_init(void)
{
CLEARSCREEN;//clear screen
LCD_write_command(0x38);//set 8 bit data transmission mode
LCD_write_command(0x0c);//open display (enable lcd display)
LCD_write_command(0x80);//set lcd first display address
CLEARSCREEN;//clear screen
}
/****************************************************/
void LCD_write_command(unsigned char command)
{
LCDIO=command;
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_EN=0;
LCD1602_EN=1;
delay_nms(10);
}
/***************************************************/
/****************写数据函数************************/
void LCD_write_dat(unsigned char dat)
{
LCDIO=dat;
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_EN=0;
delay_nms(1);
LCD1602_EN=1;
}
/****************************************************/
void LCD_set_xy( unsigned char x, unsigned char y )
{
unsigned char address;
if (y == 1)
address = 0x80 + x;
else
address =0xc0+ x;
LCD_write_command(address);
}
/***************************************************/
void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat)
{
LCD_set_xy( x, y );
LCD_write_dat(dat);
}
/**********************************************/
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
{
LCD_set_xy( X, Y );
while (*s)
{
LCD_write_dat(*s);
s ++;
}
}
/***********************************************/
void delay_nms(unsigned int n)
{
unsigned int i=0,j=0;
for (i=n;i>0;i--)
for (j=0;j<10;j++);
}
/**************************************/
void main(void)
{
unsigned char i,j,k,tmp;
LCD_init();
delay_nms(100);
tmp=0x40;//设置CGRAM地址的格式字
k=0;
for(j=0;j<8;j++)
{
for(i=0;i<8;i++)
{
LCD_write_command(tmp+i); // 设置自定义字符的 CGRAM 地址
delay_nms(2);
LCD_write_dat(table1[k]); // 向CGRAM写入自定义字符表的数据
k++;
delay_nms(2);
}
tmp=tmp+8;
}
LCD_dsp_string(1,1,"LCD TEST ");//在第一行第一列显示“LCD TEST”
LCD_dsp_string(1,2,"SUCCESSFUL ");//在第二行第一列显示“SUCCESSFUL”
for (i=0;i<4;i++)
{
LCD_dsp_char( 12+i,1,i);//在第一行第12列位置显示心图案的上半部
delay_nms(1);
}
for (i=4;i<8;i++)
{
LCD_dsp_char( 12+i-4,2,i);在第二行第12列位置显示心图案的下半部
delay_nms(1);
}
while (1);
}
/********************************************************************/