这次要做的是通过1602液晶屏幕显示一串英文Hot Display Char LCD Test
1602液晶虽然不够经济,但外观质量和背光都要比lcd5110强得多,所以这次选择使用它当作显示屏幕。
首先打开1602液晶的说明书,查看各个引脚的定义说明。
它有16个引脚。
1——GND 4——传递的是数据/命令选择(RS)
2——VCC 5——读/写选择(RW)
3——显示对比度控制 6——使能(E)
15——背光正极 7-14——D0-D7通信通道(DB)
16——背光负极
可以写出管脚定义代码代码:
/*管脚定义*/
sbit RS=P2^6;//数据与指令选择,高电平选择数据寄存器
sbit RW=P2^5;//读写选择,高电平进行读
sbit E=P2^7;//使能,由高到低液晶模块执行命令
sfr DB=0x80;//8位双向数据
然后继续查看器件说明手册。了解一下是否需要初始化,如果需要初始化,初始化时又需要做哪些动作?
从说明书中了解到,1602在显示前是需要先初始化的,初始化的目的是,告诉液晶主控芯片显示的方式是如何的。
最简单的初始化步骤是:
1设置显示模式——>2是否打开显示和是否显示光标——>3以何种方式显示多个字符?——>4清空显示缓存
1.因为1602液晶的每个小格子点阵是宽5高7的(5*7)所以要设定主控芯片的显示模式,来和液晶显示屏相匹配。
2.只有打开显示时屏幕上才会有字符显示,关闭光标屏幕上才不会出现不需要的光标
3.当显示多个字符时有两种方式,一种是类似于街边的流动广告。一种类似于KTV下面的歌词字幕。
4.如果不清空缓存刚启动时缓存里面可能会有残留数据。
了解了初始化的步骤后,继续查看说明书。了解一下1602主控芯片支持的指令有哪些。毕竟通过发送具体的指令才能初始化它。
1602液晶内部的控制器共能识别11条指令。
现在知道了主控芯片可以识别的指令,还有初始化的步骤。剩下的就是如何给主控芯片传送指令或数据了。
继续查阅1602的使用手册。
了解到,读1602内部数据的过程如下:
同是了解到,1602液晶显示模块是一个慢显示器件, 在执行每条指令之前一定要确认模块的忙标志为低电平(表示不忙)否则此指令失效。
要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符。
所以参照上面的时序图可以写出读取lcd1602是否是忙碌状态的函数。
代码如下:
/*读取LCD状态*/
void Read_State()
{
unsigned char state;
DB=0xff;//IO变输入状态
RS=0;//选择指令寄存器
RW=1;//读(参照第9条指令)
do
{
E=1;//使能
state=DB;//读取数据
E=0;
}
while( state&0x80 );//state最高位是1表示忙碌,0表示空闲
}
当写的是指令时,RS=0,当写的是数据时,RS=1。每次写之前都要先检查忙碌状态。
所以根据上面的时序图,可以写出两个函数。
代码如下:
/*写指令*/
void Write_Cmd(unsigned char cmd)//cmd为待写入的指令
{
Read_State();//LCD忙判断
RS=0;//选择指令寄存器
RW=0;//写
DB=cmd;//数据准备
E=1;//高电平
E=0;//低电平
}
/*写数据*/
void Write_Dat(unsigned char dat)//dat为待写入的数据
{
Read_State();//LCD忙判断
RS=1;//选择数据寄存器
RW=0;//写
DB=dat;//数据准备
E=1;//高电平
E=0;//低电平
}
还记得初始化的步骤吗?
1设置显示模式——>2是否打开显示和是否显示光标——>3以何种方式显示字符——>4清空显示缓存
1.显示模式设定,查阅指令6:功能设置命令
DL:高电平时为4位总线,低电平时为8位总线
N:低电平时为单行显示,高电平时双行显示
F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
/*初始化LCD*/
void Init_Lcd()
{
Write_Cmd(0x38);//显示模式5*7,使LCD控制模块和显示屏匹配
Write_Cmd(0x0c);//显示开,光标不显示,DCB
Write_Cmd(0x06);//文字不动地址增进,NS
Write_Cmd(0x01);//清屏
}
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”
如上图的lcd显示地址,了解到,要在指定位置显示字符必须先将光标移动到指定的位置。
/*设置显示位置*/
void Set_ShowPos(unsigned char x,unsigned char y)//y表示行号,0/1
{
if(y==0)
Write_Cmd( x|0x80 );//第一行的x坐标最高位为1
else
Write_Cmd( (x+0x40)|0x80 );//第二行的x坐标最高位为1
}
/*显示字符串*/
void Show_Str(unsigned char x,unsigned char y,unsigned char *str)//显示位置,字符串指针
{
Set_ShowPos( x,y );//设置显示坐标
while( *str!='\0' )
{
Write_Dat( *str++ );
}
}
#include<reg52.h>
/*管脚定义*/
sbit RS=P2^6;//数据与指令选择,高电平选择数据寄存器
sbit RW=P2^5;//读写选择,高电平进行读
sbit E=P2^7;//使能,由高到低液晶模块执行命令
sfr DB=0x80;//8位双向数据,要注意定义方法!!!!!!!!
/*全局变量定义*/
/*读取LCD状态*/
void Read_State()//这里发现问题
{
unsigned char state;
DB=0xff;//输入IO
RS=0;//选择指令寄存器
RW=1;//读
do
{
E=1;//使能
state=DB;//读取数据
E=0;
}
while( state&0x80 );
}
/*写指令*/
void Write_Cmd(unsigned char cmd)
{
Read_State();//LCD忙判断
RS=0;//选择指令寄存器
RW=0;//写
DB=cmd;//数据准备
E=1;//高电平
E=0;//低电平
}
/*写数据*/
void Write_Dat(unsigned char dat)
{
Read_State();//LCD忙判断
RS=1;//选择数据寄存器
RW=0;//写
DB=dat;//数据准备
E=1;//高电平
E=0;//低电平
}
/*设置显示位置*/
void Set_ShowPos(unsigned char x,unsigned char y)
{
if(y==0)
Write_Cmd( x|0x80 );//第一行的x坐标最高位为1
else
Write_Cmd( (x+0x40)|0x80 );//第二行的x坐标最高位为1
}
/*显示字符串*/
void Show_Str(unsigned char x,unsigned char y,unsigned char *str)
{
Set_ShowPos( x,y );//设置显示坐标
while( *str!='\0' )
{
Write_Dat( *str++ );
}
}
/*初始化LCD*/
void Init_Lcd()
{
Write_Cmd(0x38);//显示模式5*7,使LCD控制模块和显示屏匹配
Write_Cmd(0x0c);//显示开,光标不显示,DCB
Write_Cmd(0x06);//文字不动地址增进,NS
Write_Cmd(0x01);//清屏
}
lcd1602.h
//初始化函数
extern void Init_Lcd(void);
//显示字符串函数
extern void Show_Str(unsigned char x,unsigned char y,unsigned char *str);
//设置显示位置
extern void Set_ShowPos(unsigned char x,unsigned char y);
//写数据
extern void Write_Dat(unsigned char dat);
//写指令
extern void Write_Cmd(unsigned char cmd);
//读状态
extern void Read_State();
main.c
#include<reg52.h>
#include"lcd1602.h"
/*LCD1602显示字符*/
/*测试主函数*/
/*全局变量定义*/
unsigned char *str1=" HOT Display";
unsigned char *str2=" Char LCD Test";
void main()
{
Init_Lcd();//初始化LCD1602
Show_Str(0,0,str1);//显示字符串
Show_Str(0,1,str2);//显示字符串
while(1);
}