(玩电子) 电子技术学习与研讨
casino
当时方位:单片机教程网 >> MCU规划实例 >> 阅览文章

LCD1602的单片机驱动详解

作者:佚名   来历:本站原创   点击数:x  更新时刻:2014年09月20日   【字体:

一.接口

 

LCD1602是许多单片机爱好者较早触摸的字符型液晶显现器,它的主控芯片是HD44780或许其它兼容芯片。刚开始触摸它的大多是单片机的初学者。因为对它的不了解,不能为所欲为地对它进行驱动。通过一段时刻的学习,我对它的驱动有了一点点心得,今日把它记载在这儿,以备今后查阅。与此相仿的是LCD12864液晶显现器,它是一种图形点阵显现器,能显现的内容比LCD1602要丰厚得多,除了一般字符外,还能够显现点阵图画,带有汉字库的还能够显现汉字,它的并行驱动方法与LCD1602相差无几,所以,在这儿花点时刻是值得的。

一般来说,LCD1602有16条引脚,听说还有14条引脚的,与16脚的比较缺少了背光电源A(15脚)和地线K(16脚)。我手里这块LCD1602的类型是HJ1602A,是绘晶科技公司的产品,它有16条引脚。如图1所示:



图1

再来一张它的反面的,如图2所示:



图2

它的16条引脚界说如下:

引脚号

符号

引脚阐明

引脚号

符号

引脚阐明

1

VSS

电源地

9

D2

数据端口

2

VDD

电源正极

10

D3

数据端口

3

VO

偏压信号

11

D4

数据端口

4

RS

指令/数据

12

D5

数据端口

5

RW

读/写

13

D6

数据端口

6

E

使能

14

D7

数据端口

7

D0

数据端口

15

A

背光正极

8

D1

数据端口

16

K

背光负极

对这个表的阐明:

1.    VSS接电源地。

2.    VDD接+5V。

3.    VO是液晶显现的偏压信号,可接10K的3296精细电位器。或相同阻值的RM065/RM063蓝白可调电阻。见图3。


图3

4.    RS是指令/数据挑选引脚,接单片机的一个I/O,当RS为低电平时,挑选指令;当RS为高电平时,挑选数据。

5.    RW是读/写挑选引脚,接单片机的一个I/O,当RW为低电平时,向LCD1602写入指令或数据;当RW为高电平时,从LCD1602读取状况或数据。假如不需求进行读取操作,能够直接将其接VSS。

6.    E,履行指令的使能引脚,接单片机的一个I/O。

7.    D0—D7,并行数据输入/输出引脚,可接单片机的P0—P3恣意的8个I/O口。假如接P0口,P0口应该接4.7K—10K的上拉电阻。假如是4线并行驱动,只须接4个I/O口。

8.    A背光正极,可接一个10—47欧的限流电阻到VDD。

9.    K背光负极,接VSS。见图4所示。


图4

二.根本操作

LCD1602的根本操作分为四种:

1.    读状况:输入RS=0,RW=1,E=高脉冲。输出:D0—D7为状况字。

2.    读数据:输入RS=1,RW=1,E=高脉冲。输出:D0—D7为数据。

3.    写指令:输入RS=0,RW=0,E=高脉冲。输出:无。

4.    写数据:输入RS=1,RW=0,E=高脉冲。输出:无。

读操作时序图(如图5):


 图5

写操作时序图(如图6):


图6

时序时刻参数(如图7):


图7

三.DDRAM、CGROM和CGRAM

DDRAM(Display Data RAM)便是显现数据RAM,用来存放待显现的字符代码。共80个字节,其地址和屏幕的对应联络如下(如图8):


 图8

DDRAM相当于计算机的显存,咱们为了在屏幕上显现字符,就把字符代码送入显存,这样该字符就能够显现在屏幕上了。相同LCD1602共有80个字节的显存,即DDRAM。但LCD1602的显现屏幕只要16×2巨细,因而,并不是一切写入DDRAM的字符代码都能在屏幕上显现出来,只要写在上图所示规模内的字符才干够显现出来,写在规模外的字符不能显现出来。这样,咱们在程序中能够运用下面的“光标或显现移动指令”使字符渐渐移动到可见的显现规模内,看到字符的移动作用。

前面说了,为了在液晶屏幕上显现字符,就把字符代码送入DDRAM。例如,假如想在屏幕左上角显现字符‘A’,那么就把字符‘A’的字符代码41H写入DDRAM的00H地址处即可。至于怎样写入,后边会有阐明。那么为什么把字符代码写入DDRAM,就能够在相应方位显现这个代码的字符呢?咱们知道,LCD1602是一种字符点阵显现器,为了显现一种字符的字形,有必要要有这个字符的字模数据,什么叫字符的字模数据,看看下面的这个图就理解了(如图9)。


图9

上图的左边便是字符‘A’的字模数据,右边便是将左边数据用“○”代表0,用“■”代表1。然后显现出‘A’这个字形。从下面的图能够看出,字符‘A’的高4位是0100,低4位是0001,合在一起便是01000001b,即41H。它刚好与该字符的ASCII码共同,这样就给了咱们很大的便利,咱们能够在PC上运用P2=‘A’这样的语法。编译后,正好是这个字符的字符代码。

在LCD1602模块上固化了字模存储器,便是CGROM和CGRAM,HD44780内置了192个常用字符的字模,存于字符发生器CGROM(Character Generator ROM)中,别的还有8个答应用户自界说的字符发生RAM,称为CGRAM(Character Generator RAM)。下图(如图12)阐明晰CGROM和CGRAM与字符的对应联络。从ROM和RAM的姓名咱们也能够知道,ROM是早已固化在LCD1602模块中的,只能读取;而RAM是可读写的。也便是说,假如只需求在屏幕上显现已存在于CGROM中的字符,那么只须在DDRAM中写入它的字符代码就能够了;但假如要显现CGROM中没有的字符,比方摄氏温标的符号,那么就只要先在CGRAM中界说,然后再在DDRAM中写入这个自界说字符的字符代码即可。和CGROM中固化的字符不同,CGRAM中自身没有字符,所以要在DDRAM中写入某个CGROM不存在的字符,有必要在CGRAM中先界说后运用。程序退出后CGRAM中界说的字符也不复存在,下次运用时,有必要从头界说。


图10

上面这个图(如图10)阐明的是5×8点阵和5×10点阵字符的字形和光标的方位。先来说5×8点阵,它有8行5列。那么界说这样一个字符需求8个字节,每个字节的前3个位没有被运用。例如,界说摄氏温标的符号{0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00}。


 图11

上面这个图(如图11)阐明的是设置CGRAM地址指令。从这个指令的格局中咱们能够看出,它共有aaaaaa这6位,总共能够表明64个地址,即64个字节。一个5×8点阵字符共占用8个字节,那么这64个字节总共能够自界说8个字符。也便是说,上面这个图的6位地址中的DB5DB4DB3用来表明8个自界说的字符,DB2DB1DB0用来表明每个字符的8个字节。这DB5DB4DB3所表明的8个自界说字符(0--7)便是要写入DDRAM中的字符代码。咱们知道,在CGRAM中只能界说8个自界说字符,也便是只要0—7这8个字符代码,但在下面的这个表(如图12)中总共有16个字符代码(××××0000b--××××1111b)。实际上,如图所示,它只能表明8个自界说字符 (××××0000b=××××1000b, ××××0001b=××××1001b……顺次类推)。也便是说,写入DDRAM中的字符代码0和字符代码8是同一个自界说字符。 5×10点阵每个字符共占用16个字节的空间,所以CGRAM中只能界说4个这样的自界说字符。

那么如安在CGRAM中自界说字符呢?在上面的介绍中,咱们知道有一个设置CGRAM地址指令,同写DDRAM指令类似,只须设置好某个自界说字符的字模数据,然后依照上面介绍的方法,设置好CGRAM地址,顺次写入这个字模数据即可。咱们在后边的比如中再进行阐明。


 图12

四.LCD1602指令

1.工作方法设置指令(如图13)


 图13

×:不关心,也便是说这个位是0或1都能够,一般取0。

DL:设置数据接口位数。

DL=1:8位数据接口(D7—D0)。

DL=0:4位数据接口(D7—D4)。

N=0:一行显现。

N=1:两行显现。

F=0:5×8点阵字符。

F=1:5×10点阵字符。

阐明:因为是写指令字,所以RS和RW都是0。LCD1602只能用并行方法驱动,不能用串行方法驱动。而并行方法又能够挑选8位数据接口或4位数据接口。这儿咱们挑选8位数据接口(D7—D0)。咱们的设置是8位数据接口,两行显现,5×8点阵,即0b00111000也便是0x38。(留意:NF是10或11的作用是相同的,都是两行5×8点阵。因为它不能以两行5×10点阵方法进行显现,换句话说,这儿用0x38或0x3c是相同的)。

2.显现开关操控指令(如图14)


图14

D=1:显现开,D=0:显现关。

C=1:光标显现,C=0:光标不显现。

B=1:光标闪耀,B=0:光标不闪耀。

阐明:这儿的设置是显现开,不显现光标,光标不闪耀,设置字为0x0c。

3.进入形式设置指令(如图15、16)


图15

I/D=1:写入新数据后光标右移。

I/D=0:写入新数据后光标左移。

S=1:显现移动。

S=0:显现不移动。


 图16

阐明:这儿的设置是0x06。

4.光标或显现移动指令(如图17、18)


图17


 图18

阐明:在需求进行整屏移动时,这个指令十分有用,能够完成屏幕的翻滚显现作用。初始化时不运用这个指令。

5.清屏指令(如图19)


图19

阐明:铲除屏幕显现内容。光标回来屏幕左上角。履行这个指令时需求必定时刻。

6.光标归位指令(如图20)

 

 图20

阐明:光标回来屏幕左上角,它不改动屏幕显现内容。

7.设置CGRAM地址指令(如图21)


图21

阐明:这个指令在上面现已介绍过。用法在后边比如中阐明。

8.设置DDRAM地址指令(如图22)


图22

阐明:这个指令用于设置DDRAM地址。在对DDRAM进行读写之前,首先要设置DDRAM地址,然后才干进行读写。前面咱们说过,DDRAM便是LCD1602的显现存储器。咱们要在它上面进行显现,就要把要显现的字符写入DDRAM。相同,咱们想知道DDRAM某个地址上有什么字符,也要先设置DDRAM地址,然后将它读出到单片机。

9.读忙信号和地址计数器AC(如图23)


图23

阐明:这个指令用来读取LCD1602状况。关于单片机来说,LCD1602归于慢速设备。当单片机向其发送一个指令后,它将去履行这个指令。这时假如单片机再次发送下一条指令,因为LCD1602速度较慢,前一条指令还未履行完毕,它将不承受这新的指令,导致新的指令丢掉。因而这条读忙指令能够用来判别LCD1602是否忙,能否接纳单片机发来的指令。当BF=1,表明LCD1602正忙,不能承受单片机的指令;当BF=0,表明LCD1602闲暇,能够接纳单片机的指令。RS=0,表明是指令;RW=1,表明是读取。这条指令还有一个副产品:即能够得到地址记数器AC的值(address counter)。LCD1602维护了一个地址计数器AC,用来记载下一次读写CGRAM或DDRAM的方位。需求着重的是:这条指令我一次也没有履行成功。许多网友好像也是这样。好在咱们有别的的方法,也便是延时。通过查看每条指令的履行时刻,再通过一些试验,能够确认指令的延时。这样就能够在上一条指令履行完毕后再履行下一条指令了。

10.写数据到CGRAM或DDRAM指令(如图24)


图24

阐明:RS=1,数据;RW=0,写。指令履行时,要在DB7—DB0上先设置好要写入的数据,然后履行写指令。

11.从CGRAM或DDRAM读数据指令(如图25)


图25

阐明:RS=1,数据;RW=1,读。先设置好CGRAM或DDRAM的地址,然后履行读取指令。数据就被读入后DB7—DB0。

 

五.实例

下面咱们就以一个实例来完毕这篇文章。先介绍一下布景:单片机最小体系(扩大了外部RAM 62256)。选用STC89C52RC,晶振22.1184MHZ。以5×8点阵,16×2行,8位数据端口。首先在榜首行显现“I love MCU!”,第二行显现“LCD1602 Test!”。延时一段时刻,清屏。然后在榜首行显现自界说字符:摄氏温标标志。第二行显现圆周率(pai)标志。再延时一段时刻,清屏。最终在榜首行显现“Welcome to my blog!”,显现方法是从屏幕右面移入,左边移出。循环往复(如图26)。


图26

//File1

 

#ifndef __ZHANGTYPE_H__

#define __ZHANGTYPE_H__

 

#define uint8    unsigned char

#define uint16   unsigned short int

#define uint32   unsigned long int

#define int8     signed char

#define int16    signed short int

#define int32    signed long int

#define uint64   unsigned long long int

#define int64    signed long long int

 

#endif 

//File2

 

#ifndef __FUN_H__

#define __FUN_H__ 

#include "ZhangType.h"

#include  

void Delay(uint16 time); 

#endif 

//File3

 

#include "fun.h" 

void Delay(uint16 time)

{

    while(time--);

} 

//File4

 

#ifndef __1602_H__

#define __1602_H__

 

#include

#include "ZhangType.h"          //变量类型

#include "fun.h"            //常用函数 

 

#define    SETMODE    0x38          //16*2显现,5*7点阵,8位数据接口

#define DISOPEN   0x0C          //显现开,不显现光标,光标不闪耀

#define DISMODE   0x06          //读写字符后地址加1,屏显不移动

#define    SETADDR    0x80          //设置数据地址指针初始值

#define CLEAR 0x01          //清屏,数据指针清零

#define RET       0x02          //回车,数据指针清零 

#define PORT  P2            //I/O口 

 

sbit RS = P1^0;

sbit RW = P1^1;

sbit E = P1^2; 

 

void Init1602(void);        //初始化1602

void Write1602_Com(uint8 com);  //写指令

void Write1602_Dat(uint8 dat);  //写数据

void CheckBusy(void);           //查看忙

void Write1602_One_Dat(uint8 X,uint8 Y,uint8 dat);          //写一个数据

void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf);    //写一个数据串 

#endif//

//File5

 

#include "1602.h" 

 

void Write1602_Com(uint8 com)

{

    E=0;

    RS=0;                    //指令

    Delay(50);               //延时

    RW=0;                    //写         

    Delay(50);

    PORT=com;                //端口赋值

    Delay(50);

    E=1;                     //高脉冲

    Delay(50);

    E=0;

}

 

void Write1602_Dat(uint8 dat)

{

    E=0;

    RS=1;                    //数据

    Delay(50);               //延时

    RW=0;                    //写

    Delay(50);

    PORT=dat;                //端口赋值

    Delay(50);

    E=1;                     //高脉冲

    Delay(50);

    E=0;

} 

 

void CheckBusy(void)

{

    uint8 temp;

    RS=0;                    //指令

    RW=1;                    //读

    E=0;

    while(1)

    {

       PORT=0xFF;           //端口为输入

       E=1;                 //高脉冲

       temp=PORT;

       E=0;

       if ((temp&0x80)==0)      //查看BF位是否为0

           break;

    }

} 

 

void Init1602(void)

{

    Write1602_Com(SETMODE);     //形式设置

    Delay(500);

    Write1602_Com(DISOPEN);     //显现设置

    Delay(500);

    Write1602_Com(DISMODE);     //显现形式

    Delay(500);

    Write1602_Com(CLEAR);       //清屏

    Delay(500);

} 

 

void Write1602_One_Dat(uint8 x,uint8 y,uint8 dat)

{

    x&=0x0f;

    y&=0x01;

    if(y)

       x|=0x40;

    x|=0x80;

    Write1602_Com(x);

    Write1602_Dat(dat);

} 

 

void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf)

{

    uint8 i; 

    Write1602_Com(addr);

    for(i=0;i

    {

       Write1602_Dat(pbuf[i]);

    }

} 

//File6

*******************************************************

*称号:主文件(_main.c)

*功用:测验

*日期:2014/09/09

*******************************************************/

#include "1602.h"

#include "fun.h" 

uint8 code hot[8]={                                  //摄氏温度字模

0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00

};

uint8 code pi[8]={                       

0x00,0x1f,0x0a,0x0a,0x0a,0x13,0x00,0x00                 //pai

}; 

uint8 code strMCU[]="I love MCU!";

uint8 code strTest[]="LCD1602 Test!";

uint8 code blog[]="Welcome to my blog!"; 

uint8 i; 

void main()

{

    Init1602();                                      //初始化1602 

    //自界说CGRAM

    Write1602_Str(0x40,8,hot);                       //摄氏温标

    Write1602_Str(0x48,8,pi);                        //pai

 

    Write1602_Str(0x80,strlen(strMCU),strMCU);           //"I love MCU!"

    Write1602_Str(0x80+0x40,strlen(strTest),strTest);    //"LCD1602 Test!"

 

    for(i=0;i<50;i++)                             //延时一段时刻

       Delay(10000);

 

    Write1602_Com(CLEAR);                            //指令履行时刻较长

    Delay(500);                                      //多加一些延时

    for(i=0;i<16;i++)

       Write1602_Dat(0);

   

    Write1602_Com(0xc0);                          //设置DDRAM地址

    for(i=0;i<16;i++)

       Write1602_Dat(1);

    for(i=0;i<50;i++)                             //延时一段时刻

       Delay(10000);

   

    Write1602_Com(CLEAR);                            //指令履行时刻较长

    Delay(500);                                      //多加一些延时

    Write1602_Str(0x80+0x10,strlen(blog),blog);          //写在显现之外

    while(1)

    {

       Write1602_Com(0x18);                      //左移

       for(i=0;i<20;i++)                         //延时

           Delay(10000);

    }

} 

//############################# THE END #############################

宣布谈论】【告知老友】【保藏此文】【封闭窗口

文章谈论

m88 188bet uedbet 威廉希尔 明升 bwin 明升88 bodog bwin 明升m88.com 18luck 188bet unibet unibet Ladbrokes Ladbrokes casino m88明升 明升 明升 m88.com 188bet m88 明陞 uedbet赫塔菲官网 365bet官网 m88 help
188bet www.188bet.com bwin 平博 unibet 明升 188bet uk Ladbrokes 德赢vwin 188bet m88.com w88 平博88 uedbet体育 188bet 188bet 威廉希尔 明升体育app 平博88 M88 Games vwin德赢 uedbet官网 bodog fun88 188bet