51单片机外设系列:LCD1602 的详细编程

前言,LCD1602是一个比较常用的单片机显示外设,下面我们从它的显示原理,来分析用51单片机编程的思路。另外结尾还提供了完成的程序代码参考。

一、LCD1602的外观、结构和基本参数

引脚功能解析:

第1引脚:GND为电源地脚。

第2引脚:VCC接5V电源正极。

第3引脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高。

第4引脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。

第5引脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。

第6引脚:E(或EN)端为使能(enable)端,高电平(1)时读取信息,负跳变时执行指令。

第7~14引脚:D0~D7为8位双向数据端。

第15~16脚:空脚或背灯电源。第15引脚背光正极,第16引脚背光负极。

二、电路接线图

RD(也就是RS)\RW\E接口分别接单片机的1.1、1.2、1.3位。LCD0~7接P0刚好八个。

三、LCD1602的显示原理分析

LCD1602之所以是1602是因为它能够显示16(列)*2(行)个字符,如下图所示:

其实LCD1602编程显示的原理并不是很难,简单来说就是要做好两步。

第一步就是要找出我们显示字符的位置

比如我们想把字符显示在上图的第一行的第九个位置,那么就可以选定08。08换算成二进制就是0000 1000。

但是还有个需要注意的地方就是,如果是要写入显示的地址信息的时候,D7是要求为高电平的。那么08就要变成10001000。就是88(0x88)。

第二步发送要显示的字符,1602的参考手册给出了查询字符的表格。如下:

如图上所示,如果我们想发送一个D,那么我们只要找出来0100 0100,转换成16进制的就是0x44, 刚好对应Ascll码68。实际上我们输入的时候输入字符就可以了。编译器会自动转换成对应的Ascll码的。

这两个步骤,一个是传输地址,一个是传输字符。那么怎么去区分呢。通过RS引脚来做区分,RS为高电平1时选择数据寄存器(写数据)、低电平0时选择指令寄存器(写地址)。

四、LCD1602时序分析

①写操作的时序分析

RS:地址命令和数据的选择,写地址命令为0,写数据为1。

R/W:读和写的选择,0是写,1是读。可以从上图的时序可以看出来R/W贯穿了整个时序,因此我们将R/W置0即可。

E:初始状态为0,

然后延时至少tR之后置1(tR的值参考上表,25ns执行一个_nop_()函数就可以满足),

置1后要延时至少tPW(上图给出的tPW值为150ns,建议执行两个_nop_()函数),

接着再至少延时tF(执行一个_nop_()函数)后置0。

参考程序如下:

void Write_Cmd(unsigned char cmd)

{

Busy_Check();

Lcd_Rs=0;//写“地址命令标志”

Lcd_Rw=0;

Lcd_En=0;

_nop(); //执行一个空函数,延时月1us

P0=cmd;

Lcd_En=1;

_nop();

_nop();

Lcd_En=0;

_nop();

}

void Write_Dat(unsigned char dat)

{

Busy_Check();

Lcd_Rs=1;//写“ 数据”标志

Lcd_Rw=0;

Lcd_En=0;

_nop(); //执行一个空函数,延时月1us

P0=dat;

Lcd_En=1;

_nop();

_nop();

Lcd_En=0;

_nop();

}

读操作的时序和写操作的时序有点区别。读操作时序与写操作时序的区别在于:写操作时序在E=0的时候就开始传输数据,而读操作时序要等E=1之后才开始传输数据。

②读操作的时序分析

RS:因为是写入命令,所以这里是0。

RW:读标志,置1。

E:初始状态为0,延时tR后拉高,之后再延时tPW后拉低。

参考程序:

void Busy_Check(void) //判断是否忙碌的函数。

{

P0=0xFF;

do

{

Lcd_Rs=0;

Lcd_Rw=1;

Lcd_En=0;

_nop();

Lcd_En=1;

_nop();

_nop();

} while(Lcd_Busy==1) ;

Lcd_En=0;

_nop();

}

五、LCD1602的初始化

查看手册的时候可以看到初始化的说明

这里我们做了程序的简化:

void Lcd1602_Init(void)

{

Write_Cmd(0x38);

Write_Cmd(0x0C);

Write_Cmd(0x06);

Write_Cmd(0x01);

}

完整代码:

一、LCD1602 显示一个字符,参考程序

#include <reg52.h>

sbit Lcd_Rs=P1^2;// 通过位操作把LCD的命令、使能、数据引脚等跟单片机的对应IO定义好。

sbit Lcd_Rw=P1^3;

sbit Lcd_En=P1^4;

sbit Lcd_Busy=P0^7; //这个是LCD的忙碌标志,通过获取这个引脚的电平就可以判断LCD是否在忙碌,

void Busy_Check(void) //判断是否忙碌的函数。

{

P0=0xFF;

do

{

Lcd_Rs=0;

Lcd_Rw=1;

Lcd_En=0;

_nop();

Lcd_En=1;

_nop();

_nop();

} while(Lcd_Busy==1) ;

Lcd_En=0;

_nop();

}

void Write_Cmd(unsigned char cmd)

{

Busy_Check();

Lcd_Rs=0;//写“地址命令标志”

Lcd_Rw=0;

Lcd_En=0;

_nop(); //执行一个空函数,延时月1us

P0=cmd;

Lcd_En=1;

_nop();

_nop();

Lcd_En=0;

_nop();

}

void Write_Dat(unsigned char dat)

{

Busy_Check();

Lcd_Rs=1;//写“ 数据”标志

Lcd_Rw=0;

Lcd_En=0;

_nop(); //执行一个空函数,延时月1us

P0=dat;

Lcd_En=1;

_nop();

_nop();

Lcd_En=0;

_nop();

}

void Lcd1602_Init(void)

{

Write_Cmd(0x38);

Write_Cmd(0x0C);

Write_Cmd(0x06);

Write_Cmd(0x01);

}

void main(void)

{

Lcd1602_Init();

Write_Cmd(0x80+0x08);// 发送命令,规定显示的位置。

Write_Dat('x') ;// 发送显示的数据。

while(1);

}

显示效果如下:

二、LCD1602显示字符串,参考程序

#include <reg52.h>

#include <intrins.h>

sbit Lcd_Rs=P1^2;// 通过位操作把LCD的命令、使能、数据引脚等跟单片机的对应IO定义好。

sbit Lcd_Rw=P1^3;

sbit Lcd_En=P1^4;

sbit Lcd_Busy=P0^7; //这个是LCD的忙碌标志,通过获取这个引脚的电平就可以判断LCD是否在忙碌,

unsigned char code str1[]={"12345678"};

unsigned char code str2[]={"zhongguojiayou"};

void Busy_Check(void) //判断是否忙碌的函数。

{

P0=0xFF;

do

{

Lcd_Rs=0;

Lcd_Rw=1;

Lcd_En=0;

_nop();

Lcd_En=1;

_nop();

_nop();

} while(Lcd_Busy==1) ;

Lcd_En=0;

_nop();

}

void Write_Cmd(unsigned char cmd)

{

Busy_Check();

Lcd_Rs=0;//写“地址命令标志”

Lcd_Rw=0;

Lcd_En=0;

_nop(); //执行一个空函数,延时月1us

P0=cmd;

Lcd_En=1;

_nop();

_nop();

Lcd_En=0;

_nop();

}

void Write_Dat(unsigned char dat)

{

Busy_Check();

Lcd_Rs=1;//写“ 数据”标志

Lcd_Rw=0;

Lcd_En=0;

_nop(); //执行一个空函数,延时月1us

P0=dat;

Lcd_En=1;

_nop();

_nop();

Lcd_En=0;

_nop();

}

void Write_String(unsigned char addr_sta,unsigned char *p)

{

Write_Cmd(addr_sta) ;

while(*p!='\0')

{

Write_Dat(*p++);

}

}

void Lcd1602_Init(void)

{

Write_Cmd(0x38);

Write_Cmd(0x0C);

Write_Cmd(0x06);

Write_Cmd(0x01);

}

void main(void)

{

Lcd1602_Init();

Write_String(0x80,str1);// 发送字符串1的位置和数据。

Write_String(0xC0,str2);// 发送字符串2的位置和数据。

while(1);

}

显示效果如下:

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机外设系列:LCD1602 的详细编程

发表评论