单片机液晶屏显示教程,好玩的单片机如何使用1602液晶屏
单片机液晶屏显示教程,好玩的单片机如何使用1602液晶屏第三步:DB0~DB7的数据才是有效数据“Valid Data”,此时我们把数据或者指令赋值给DB0~DB7;第二步:将RW引脚拉低(写操作,若是读操作RW引脚拉高);说了这么多,那么我们怎样才能将“数据”或者“指令”写入1602呢?这里就需要理解1602液晶屏的时序了。时序,通俗的说就是芯片设定好的引脚电平状态和时间的关系,只有根据这个关系芯片才能完成制定的工作。实际操作中一般只对1602进行写操作,写操作的时序图如下所示。时序图看起来很复杂,其实我们只要抓住关键的几个点就可以了。根据时序图,第一步:确定是写指令还是写数据:如果我们要向1602写命令,那么RS引脚拉低;若向1602写数据,那么RS引脚拉高;
上一节讲了如何用蜂鸣器播放音乐,好玩的单片机——怎样用蜂鸣器播放音乐“敢问路在何方”。这一节讲下1602液晶屏的操作,搭建的proteus仿真图如下图。
1602液晶屏有16只引脚,其含义为:
VDD引脚是电源脚,1602液晶屏最佳工作电压是5V;VO引脚用于调整1602显示的对比度,一般会外接电位器用以调整偏压信号(该引脚电压为0时对比度最高);
RS引脚为数据/命令选择端,该引脚高电平时1602操作的是数据,而低电平时1602操作的是命令。数据就是我们要让1602液晶屏显示的具体内容,而命令就是对1602的设置(比如光标是否闪烁等);
1602液晶屏是字符型液晶屏,其内置含128个字符的ASCII字符集字库,只能显示ASCII码字符,每行显示16个字符,总共能显示两行。如实物图所示,第一行第一列显示了“A”,那如何写程序才能做到呢?首先我们得知道1602液晶屏内部带有80B的RAM缓冲区,其中第一行的地址从00H~0FH,第二行的地址从40H~4FH都是能显示的,若超出地址范围则必须通过移屏指令,移入到00H~0FH或者40H~4FH范围内才能显示,其次1602液晶屏内部的地址指针从80H开始。回到刚才的问题,我们需要设置数据地址指针为(80H 00H),并把字符‘A’写入1602液晶屏,那么1602液晶屏的第一行第一列就显示字符A了。
说了这么多,那么我们怎样才能将“数据”或者“指令”写入1602呢?这里就需要理解1602液晶屏的时序了。时序,通俗的说就是芯片设定好的引脚电平状态和时间的关系,只有根据这个关系芯片才能完成制定的工作。实际操作中一般只对1602进行写操作,写操作的时序图如下所示。
时序图看起来很复杂,其实我们只要抓住关键的几个点就可以了。根据时序图,
第一步:确定是写指令还是写数据:如果我们要向1602写命令,那么RS引脚拉低;若向1602写数据,那么RS引脚拉高;
第二步:将RW引脚拉低(写操作,若是读操作RW引脚拉高);
第三步:DB0~DB7的数据才是有效数据“Valid Data”,此时我们把数据或者指令赋值给DB0~DB7;
第四步:E引脚给一个高脉冲,持续时间tpw最小值为150ns,然后E引脚再次拉低。
通过上述四个步骤就可以对1602进行一次写操作了。由于1602时序图时间是ns级,而AT89C52单片机指令周期是us级,所以即使不在程序里加延时程序,也应该可以很好的配合1602的时序要求,不过为了液晶显示的稳定,最好加上短延时,大家可以在仿真的时候试试不同值的延时。
好了,到这里就可以开始写程序了,让1602液晶屏第一行显示“Toutiao:”,第二行显示“di ya dian qi”。
#include<reg52.h>
#include<intrins.h> //包含这个头文件才能调用-nop_()延时函数(延时一个机器周期)
#define uchar unsigned char
#define uint unsigned int
uchar code DISPLAY1[] = "Tou tiao:"; //1602液晶屏第一行显示的内容
uchar code DISPLAY2[] = "di ya dian qi"; //1602液晶屏第二行显示的内容
sbit lcd_RS = P2^0;
sbit lcd_RW = P2^1;
sbit lcd_EN = P2^2;
sfr DBPort = 0x80; //1602液晶屏8位并行口D0~D7连接单片机P0口
#define LCD_COMMAND 0 //RS低电平写命令
#define LCD_DATA 1 //RS高电平写数据
void delayxms(uint xms); //延时
void LCD_Write(bit style uchar input);//1602写操作函数,style值决定是写入命令还是写入数据,input是P0口的值
void LCD_Initial();//1602初始化函数
void delayxms(uint xms)
{
uint i j = 0;
for(i = xms;i > 0;i--)
for(j = 110;j > 0;j--);
}
//LCD_Write函数的代码,大家要对照着时序图看就明白了。
void LCD_Write(bit style unsigned char input)
{
lcd_RS = style;//RS高电平表示写数据,低电平表示写命令
lcd_RW = 0; //RW低电平表示写操作
_nop_(); //延时一个机器周期
DBPort = input; //向P0口赋值,也就是向1602的D0~D7这8位并行口赋值
_nop_();
lcd_EN = 1; //E引脚拉高
_nop_();
lcd_EN = 0; //延时之后E引脚再拉低,表示给E引脚一个高脉冲
delayxms(1);//这个延时很关键,保证向1602不断的写数据时E引脚能实现一个高脉冲
}
void LCD_Initial()
{
lcd_EN = 0;//初始化时E引脚拉低,为后续给E引脚高脉冲做好准备
LCD_Write(LCD_COMMAND 0x38); //设置16*2显示
LCD_Write(LCD_COMMAND 0x0C); //设置开显示,光标不显示且不闪烁
LCD_Write(LCD_COMMAND 0x06); //写一个字符后地址指针 1
LCD_Write(LCD_COMMAND 0x01); //显示清零,数据地址指针清零
}
void main(void)
{
uint index1 index2 = 0;//第一行和第二行要显示的内容的序号
LCD_Initial();
LCD_Write(LCD_COMMAND 0x80);//光标定位在第一行第一列
for(index1 = 0;index1 < 9;index1 )
{
LCD_Write(LCD_DATA DISPLAY1[index1]);//依次写入“Toutiao:”
delayxms(1);//每写完一个字符后延时,使得1602显示稳定
}
LCD_Write(LCD_COMMAND 0x80 0x40);//光标定位在第二行第一列
for(index2 = 0;index2 < 13;index2 )
{
LCD_Write(LCD_DATA DISPLAY2[index2]);//依次写入““di ya dian qi”
delayxms(1);
}
while(1);//程序死循环,1602静态显示
}
最终的效果如图所示,下一节继续讲下1602的初始化设置方面的内容,以及移入显示的效果。