目录
- 1.LCD1602介绍
-
- [1.1 LCD1602简介](#1.1 LCD1602简介)
- [1.2 内部介绍](#1.2 内部介绍)
- [1.3 LCD1602常用指令](#1.3 LCD1602常用指令)
-
- [1.3.1 清屏指令](#1.3.1 清屏指令)
- [1.2.2 模式设置指令](#1.2.2 模式设置指令)
- [1.2.3 显示开光控制指令](#1.2.3 显示开光控制指令)
- [1.2.4 功能设置指令](#1.2.4 功能设置指令)
- [1.4 LCD1602使用](#1.4 LCD1602使用)
- 2.硬件设计
- 3.软件设计
-
- [3.1 写命令和写数据](#3.1 写命令和写数据)
- [3.2 初始化1602](#3.2 初始化1602)
- [3.3 清屏](#3.3 清屏)
- [3.4 显示字符串](#3.4 显示字符串)
- [3.5 单个字符显示](#3.5 单个字符显示)
- [3.6 代码整合](#3.6 代码整合)
- 4.实验现象
1.LCD1602介绍
LCD1602为什么叫1602呢?
1602叫做1602字符型液晶,从名字可以知道,它只能显示字符,并且能显示两行的字符信息,每一行能显示16个字符,所以一行能显示16个字符,只能显示两行,所以吧这个行显示的字符数,合并起来就叫做1602,这就是1602的命名。
LCD1602是一种专门显示字母数字,负号一种点阵型液晶模块,它是由若干个5 * 7或者是5 * 10,这么一个大小的点阵字符位组成,这个57和5 10后续会根据我们写入对应的命令,选择是57还是510,通常我们使用的5*7的。
5*7的理解:
比如我在1602上面显示一个字符0,每一位占据的这个点,这个点就是一个点阵,点呢一行有5个,列有7个,所以这样组成的是一个字符的显示。
LCD1602还有一点需要注意的是,它的每一个点阵字符位,第一个显示字符位,第二个显示字符位,中间有一个间隔,并且第一行与第二行之间它也有一个间隔,因此这个间隔起到字符间距和行间距的作用,正因为如此它就不能很好的显示图片,我们知道图片是连续的,如果说在1602上面因为存在间隙所以在显示图片上面呢无法显示完美图片,所以1602仅限制显示一些字符的数据,比如说字母,数字,还有一些符号等等。
1.1 LCD1602简介

从图中可以看出LCD1602总共16个引脚
1号管脚:电源GND
2号管脚:电源正极
这里对应的连接到51单片机的5V的
3号引脚:VL引脚
这个引脚用来显示偏压信号,用来调整LCD1602显示对比度,就是有时候会出现将LCD1602插入到开发板的时候,下载1602实验程序,结果屏幕上没有显示任何信息,只有一个背光亮,这时候有可能是VL的偏压信号过大,所以需要在3号引脚接一个电位器,让对比度进行调节,当显示没有信息的时候,可以通过调节电位器改变偏压信号,当1602显示最亮的时候,这个偏压信号通常是0V的,所以说通过改变定位器的旋转角度,可以改变VL偏压信号,从而让对比度进行调节,从而让我们显示在字符更亮更清晰。
4号引脚:RS引脚,数据/命令的选择控制引脚(H/L)
这里的H和L代表如果这个引脚是高电平的时候选择的是数据功能,如果这个引脚是低电平的时候选择的是命令功能,因为让1602进行显示,首先需要初始化对应的一些命令,将这些命令写入到1602内部控制器当中,首先我们初始化的时候需要对它的命令进行操作,因此将RS引脚设置低电平,设置命令写入之后,接下来开始写入对应的数据,也就是我们要吧数据放到1602当中显示,那显示数据就让RS引脚设置高电平,也就是选择数据写入功能。
5号引脚:R/W引脚
从名字可以知道,R是读的功能,W是写的功能,所以通过这个管脚的高低电平控制,高电平是用来选择读,低电平是用来选择写,但是我们在使用1602的时候很少使用读的功能,我们通常情况下,将我们要显示的数据写入上面进行显示就可以了。
6号引脚:使能信号
这个使能信号是根据我们要写入的数据,它需要按照它的一个时序,首先是一个上升沿,然后是一个下降沿,通过这么一个时序,将我们的数据写入到对应的1602里面,所以这个使能信号要配合时序图来操作1602.
7号 - 14号管脚:D0 - D7
一共是8个引脚,这个是并行数据口,而我们的51单片机IO口一组正好也是8位,这样以来我们就可以通过一组IO,比如说我们用P0端口,P0.0-P0.7对应的接入到D0 - D7,我们需要控制P0口,就可以对数据的写入。
15号引脚:背光正极
16号引脚:背光负极
在1602左边有个像灯泡样的,通过这个灯泡发光,射入到1602屏内部,这样可以有一个背光显示,如果没有这个背光的话,那么我们在看显示数据的时候,就相当于手机在没有光的情况下显示数据,就会看的不是很清楚。
1.2 内部介绍
LCD1602内部含有80个字节的DDRAM,这个用来寄存显示字符的,我们要显示什么东西,就需要我们吧什么东西存储到DDRAM当中的,这里说内部含有80个字节,但是通过前面对1602介绍,一行只能显示16个字符,两行就是32个字符,32个字节数据为什么需要80个字节存储呢,因此,这个80字节数据并不是说我们所有的显示屏这些东西,都能显示在80个里面,这个需要注意的是1602屏对应的DDRAM的地址是固定的。
从这个图中看到,最上面一张图,第一行介绍显示位置,第二行介绍是用来显示LCD1602的第一行显示的字符地址从00H-27H总共是40个,第三行介绍用来显示LCD1602的第二行显示的字符地址从40H - 67H也是40个,因此总共是80个DDRAM的字节。
那么我们第一行总共显示16个字符,对应的16个之后的呢,就是下面一张图,这个是实际的1602屏对应的显示区间就是在00 - 0F是16个和40 - 4F是16个,总共是32个,而后面10 - 27和50 - 67这些是剩余的DDRAM的字节,如果之间吧数据显示到10 - 27和50 - 67RAM当中,它是不能之间在1602屏上显示的,这些RAM的存储空间,只能让我们存储一些数据,并不能直接显示,我们可以显示的数据的地址是00 - 0F和40 - 4F,所以在使用1602屏的时候这一点需要特别注意。
在这里还需要注意一个重要一点,我们知道DDRAM一个地址对应的1602屏的显示位置,比如说我们让地址是02这个位置显示一个数字1,怎么让第一行第三个位置显示数字1呢,首先我们需要将数据显示到这个地址位置,这地址呢是02,但是是不是就是02呢,在这里我们可以看到下面第三个图,这里有一个指令编码,这是对DDRAM地址的设定,我们知道DDRAM地址是有7位的,最高位固定为1的,因此我们要操作DDRAM的地址,我们必须保证最高位是设置1,所以这个知道后,我们在第一行第三个位置显示数字1,这个地址并不是02,还需要加最高位为1,也就是0x80,这个0x80二进制是1000 0000,最高位就是1嘛,所以这个地址是02 + 0x80,这个加就相当于或运算,这里02 | 0x80运算结果就是0x82嘛,因此如果我想要在第一行第三个位置显示数字1的话,将1写入地址是0x82,而第一行的第三个地址是02是没有指定DDRAM地址的最高位为1的,因此我们自己需要加进去,这是特别需要注意的一点。
然后我们显示1的话,是不是将这个10进制的1写入进去呢,这是不行的,1602是一个字符型的数据,我们写进去的必须是字符型,ASCII码的一个编码数据,我们要将十进制的1转换成ASCII码数据,1 + 0X30,这里的0X30对应的是'0'的16进制的值,那么我们吧1 + 0X30那么不就是0X31嘛,0X31对应的字符型ASCII不就是'1'的值嘛,所以我们通过1 + 0X30的操作在第一行第三个位置显示1。
1.3 LCD1602常用指令
前面说了1602屏要对它进行显示,首先需要对它一些命令进行写入,常见的命令如下
1.3.1 清屏指令

1602数据是一个8位并行口,所以D0 - D7对应的数据是0X01,清屏指令是固定的,所以我们只需要发送一个0X01给1602写进去,它会完成一个清屏的动作,清屏就是相当于清除液晶显示器上面的数据,因为我们的数据存放在80个字节DDRAM当中的,那么它就是将DDRAM里面的数据全部填写空白,对应ASCII数据是20H,它吧DDRAM数据全部去掉,填入一个空白,那么在1602屏上面不就是显示空白了嘛,就相当于没有显示嘛,类似于清屏的动作。
1.2.2 模式设置指令

用来设置1602屏的光标,移动方向,还有显示屏的移动方向,前面RS引脚低电平的是对命令的操作,第一位就是0,并且是将数据写入到1602里面所以是写功能,也就是第二位也是0,这一块是对命令写入的说明,D7 - D0就是写入一个字节的数据,前面D7 - D2都是固定的,0000 01,后面D1和D0是可变的,也就是I/D和S。
I/D可以设置1也可以设置0,当I/D设置1的时候,写入数据之后,光标是往后移动一位,也就是向右移动,所以这里设置1。如果I/D设置0的话,光标往前移动,也就是向左移动。
S可以设置0或者1,如果设置1的话,写入新的数据之后,显示屏整体右移动,如果设置0的话,写入新的数据之后,显示屏不移动。
那我们只需要保证光标移动就行了,显示屏不让它移动,所以S设置0,I/D设置1,所以D1设置1,D0设置0,就是10
那么对应一个字节的数据是0000 0110就是0X06,所以当我们写入0X06命令后,就可以设置光标右移动和显示屏不移动。
1.2.3 显示开光控制指令

从这个指令可以看到RS和R/W依然是0 0 它是命令,并且是写入的指令,然后D7 - D0是八位数据,前面D7 - D2是固定的,0000 1,后面可变的是三位 D2 - D0。
D:表示显示功能的控制。
如果设置0的时候,显示功能是关闭的,1602处于关闭的显示状态,如果设置1的时候,显示功能开启的状态,那我们使用1602的话希望它开启,所以这一位设置1。
C:设置是否有光标。
如果设置0的时候,不显示光标的,如果设置1的时候,就显示光标,在使用1602的时候这个可以自己去选择,是否使用光标,那我这里不使用光标,所以这里设置0。
B:设置光标是否闪烁。
同样了当我使用了光标,光标闪烁和不闪烁才有效,如果我没有使用光标,将C设置了0,对于光标闪烁和不闪烁是不存在了,因为我都已经关闭了光标功能,所以这一位是0还是1都不影响,当C设置了1的时候,使用光标,那么B这一位才需要设置光标是否闪烁,B设置0光标闪烁,B设置1光标不闪烁,但是我们这里设置0
所以通过前面D7 - D2固定是0000 1 后三位设置1 0 0,最终八位的数据是0000 1100 对应的16进制是0X0C。
1.2.4 功能设置指令

这个指令是对1602数据总线位数,以及显示的行数,以及字符型,来进行选择设置。
我们在这个指令当中RS和R/W这个指令都是设置0,代表的是命令,并且是写入的功能,这个数据前面三位是固定的D7 - D5是0 0 1,后面D4 - D0不是固定的,是需要设置选择的。最后D1和D0设置的是XX表示设置任意值都可以,设置0或者1都可以。但是通常设置0 0,所以D1和D0设置0 0。所以可选择的是三位 D4 - D2。
DL:设置数据总线位数
前面介绍1602屏说过,1602屏它有8位,DB0 - DB7一共8位并行口,有的厂家它为了缩小1602管脚数目,节省IO口嘛,它可以做成4位,这四位可以做到DB0和DB3,这样连接IO口的时候就减掉4个,所以对于IO比较少,比较紧张的芯片可以使用4位的1602,但是比较常见常用的还是8位的,所以根据DL这一位使用的1602屏来选择,比如我们使用的是8位,就需要将DL设置1,这一位设置1的话,数据总线是8位的,如果这一位设置0的话,它就是4位数据总线。但是4位数据总线跟8位数据总线类似,数据命令一样传送,比如在开关命令的是0X0C,那么如果是4位的数据总线的话,需要传送两次,先传高位0X0,再传低位0XC,这个就可以将8位传送到4位数据总线上,分两次传,每次传4位,从高位开始传送。
所以我们的数据总线是8位,这位设置1。
N:设置1602显示行
我们1602本来可以显示2行的,当然也可以设置显示1行,那么怎么设置,就是需要对这个N进行设置,如果N设置0,那么显示的1602是一行,如果N设置1,那么显示1602是两行,就像我们使用1602肯定希望显示的内容更多一点,所以我们显示两行设置1。
F:设置每一个字符占据的点阵数
前面介绍1602屏的时候,1602屏是一个点阵字符型的点阵屏,它的每一个字符都占据点阵数,这个点阵数可以是
5 * 7的也可以是5 * 10的,就需要通过F位进行设置,如果这一位设置0的话,使用更多是57的点阵,就是每一个字符占据57的,这里的5 * 7,每一行是5个点,有7行,如果这一位设置1的话,就是5 * 10点阵,通常情况下我们使用的是5 * 7的,所以这一位设置0。
前面D7 - D5设置001
所以最后D4 - D2设置的是110
最后两位是任意,通常设置00
这八位分别是0011 1000对应的16进制是0X38
1.4 LCD1602使用
要使用1602首先需要对1602进行初始化,也就是说通过一些特殊的指令,来写入到1602屏里面,这个指令前面介绍了4条指令,然后写完指令之后,初始化完成之后,我们要选择要在1602哪一个位置进行显示,并且将所要显示的数据发送到1602的DDRAM当中,要使用LCD1602通常用于写数据到1602里面进行显示,很少用到读的功能,所以对RS和R/W引脚通常我们设置0,有些其他开发板会吧R/W引脚直接接到GND,这样腾出一个IO口,但是为了更灵活,还是吧R/W引脚接入到单片机IO口当中。
LCD1602的使用主要包括三点:
① 初始化
将一些命令写入到1602里面。
②写命令(RS = L),设置显示坐标
因为我们1602可以显示32个字符,第一行显示16个,第二行显示16个,但是要显示在哪里,需要设置位置。
③写数据(RS = H)

要对它进行写,写命令和写数据,它会有一个使能管脚E,也就是6号管脚,如何让写命令和写数据写入到1602里面来呢,这里就有上面一个时序图。
RS引脚是写命令和写数据的4号引脚,低电平写命令功能。
RW引脚高电平是用来选择读,低电平是用来选择写,5号引脚,我们要对它进行写操作,读很少用到。直接设置该管脚0。
E引脚是使能信号引脚,6号引脚。
DB0-DB7是八位数据口,我们要写入数据,将数据传入到DB0-DB7当中,但是从时序图中可以看到,有效的数据在Valid data区间
这块区间可以看到RS和R/W指定好之后,要吧数据传入到DB0-DB7当中,这个E从低电平变成高电平有一个上升沿的过程,然后持续一段时间之后,又从高电平跳变成低电平,一个下降沿,然后DB0到DB7数据完成了写入

但是在这个时序图中有许多参数,tsp1、tHD1、tpw、tR、tsp2等等这些数据时间,这些时间都是一些纳秒级的,这个可以通过数据手册LCD1602,对应的时间参数。
可以从图中看到,最大值单位都是纳秒级别,但是我们的单片机一个机器周期都需要1us,对于我们外部晶振12M的话,那么我们需要2-4个机器周期,需要2-4个us,所以这个时间是完全足够的,但是为了让通信更稳定,可以加入一些延时,1ms,1us等等
2.硬件设计

1号引脚接GND
2号引脚VCC
3号引脚V0连接电位器,通过调节电位器来调节LCD1602对比度
4号引脚RS接到单片机IO口P2.6,用来写命令和写数据引脚
5号引脚RW连接到单片机IO口P2.5,用来读写操作,但是我们很少用到读操作,一般用写比较多
6号引脚E连接到单片机IO口P2.7,使能引脚
7号引脚到14号引脚对应的是DB0到D07,连接到单片机IO口的P0.0 - P0.7
15号引脚连接VCC,背光源正极
16号引脚连接到GND,背光源负极
3.软件设计
实现功能:在LCD1602显示字符信息
引脚定义
c
sbit LCD1602_WR = P2^5;
sbit LCD1602_RS = P2^6;
sbit LCD1602_EN = P2^7;
#define LCD1602_DATAPORT P0
3.1 写命令和写数据
c
//写命令
void lcd1602_write_cmd(u8 cmd)
{
LCD1602_RS = 0; //低电平写命令
LCD1602_WR = 0;
LCD1602_EN = 0;
LCD1602_DATAPORT = cmd;
delay_ms(1);
LCD1602_EN = 1;
delay_ms(1);
LCD1602_EN = 0;
}
//写数据
void lcd1602_write_data(u8 dat)
{
LCD1602_RS = 1; //高电平写数据
LCD1602_WR = 0;
LCD1602_EN = 0;
LCD1602_DATAPORT = dat;
delay_ms(1);
LCD1602_EN = 1;
delay_ms(1);
LCD1602_EN = 0;
}

这里写命令和写数据,主要改变了RS,设置RS是低电平的时候是写命令,高电平的时候是写数据。
根据时序图理解代码:
RS在时序图中可以高电平也可以是低电平,当我在写命令的代码中,这里将RS设置0,写数据代码中,RS设置1,R/W时序图中我要写入数据,所以RW也要低电平,可以从时序图中看出,DB0 - DB7数据是在E使能端的高电平的时候写入进去的,所以在代码中,先将EN初始化0,然后将要传入的8个数据放到单片机IO口,给一个短暂的延时,然后将EN拉高电平,此时将单片机IO口的数据送入进去了,然后短暂的延时,最后拉低使能端结束。
3.2 初始化1602
c
//初始化1602
void lcd1602_init(void)
{
lcd1602_write_cmd(0X38); //设置1602 8位数据总线 2行 每一个数据是5*7点阵
lcd1602_write_cmd(0x0C); //设置1602 开启显示功能 是否使用光标 光标是否闪烁
//这里设置的不使用光标 如果设置不使用光标 光标闪烁设置0和1无所谓,这里设置0
lcd1602_write_cmd(0X06); //设置光标移动方向和显示屏移动
//这里每当写入一个数据后,光标后移动一位,以及屏幕整体不动进行设置
lcd1602_write_cmd(0X01); //清屏指令设置
}
这里设置了4个命令,在目录1.3也介绍了, 同时根据注释也可以看到为什么设置对应的16进制
0x38
设置1602 8位数据总线 2行 每一个数据是5*7点阵,这里的5 * 7是每一个显示的字符是在7行,5列点阵中显示
0x0X
设置1602 开启显示功能 是否使用光标 光标是否闪烁
0x06
设置光标移动方向和显示屏移动,这里每当写入一个数据后,光标后移动一位,以及屏幕整体不动进行设置
0X01
设置清除屏幕的数据
3.3 清屏
c
void lcd1602_clear(void)
{
lcd1602_write_cmd(0x01);
}
3.4 显示字符串
c
//在指定的坐标位置显示字符
//x: 0-15
//y: 0-1
void lcd1602_show_string(u8 x, u8 y, u8* str)
{
u8 i = 0;
if (x > 15 || y > 1) return;
if (y < 1) //第一行
{
while((*str) != '\0')
{
//找到需要写入的位置
if(i < 16)
lcd1602_write_cmd(0x80 + x + i);
else
lcd1602_write_cmd(0x80 + 0x40 + x + i - 16);
//写入数据
lcd1602_write_data(*str);
str++;
i++;
}
}
else //第二行
{
while((*str) != '\0')
{
//找到需要写入的位置
if(i < 16 - x)
lcd1602_write_cmd(0x80 + 0x40 + x + i); //第二行
else
lcd1602_write_cmd(0x80 + x + i - 16); //第一行
//写入数据
lcd1602_write_data(*str);
str++;
i++;
}
}
}
这个函数有三个参数,x,y,str,其中x是用来表示指定第几列的,y表示指定第几行的,str是要显示的字符串
开始通过
c
if (x > 15 || y > 1) return;
判断显示的位置是否合法
接着用
c
if (y < 1)
{
}
else
{
}
这个语句是要显示在1602中第一行还是第二行显示,y是0的时候显示在第一行,y是1的时候显示在第二行
如果显示第一行,进入if里面
c
while((*str) != '\0')
{
//找到需要写入的位置
if(i < 16 - x)
lcd1602_write_cmd(0x80 + x + i);
else
lcd1602_write_cmd(0x80 + 0x40 + x + i - 16);
//写入数据
lcd1602_write_data(*str);
str++;
i++;
}
这个while是用来遍历字符串,字符串末尾有一个结束是字符'\0',判断当前的字符是不是'\0'如果不是说明没有结束
我们知道1602可以显示2行数据,每一行只能显示16个字符,所以需要用
c
if(i < 16-x)
{}
else
{}
如果 i 小于16 - x,我们知道1602一行只能显示16个字符,如果我x设置3,表示从第一行第三个字符开始,一直到第16个位置结束,第一行总共可以显示16-3就是13个字符,第一行就只能显示13个字符,i是用来遍历当前字符个数,i是从0开始的,表示第一个字符,当i是12的时候,此时就是第13个字符,12 <13 成立的,此时第一行的13个字符满了,就执行else,将剩余没有显示的字符放在1602的第二行显示出来,所以else执行的功能是将剩余在第一行没有显示完的字符放到第二行上显示。

c
lcd1602_write_cmd(0x80 + x + i);
从上面图中看到,起始地址是0x80
0x80+0第一行第一个
0x80+1第一行第二个
0x80+2第一行第三个
...
0x80+15第一行第十六个
这里的x是设置开始时候,起始位置,假设x是3的话
0x80 + 3起始位置是第一行第四个位置
后面 i 是用来从第一行第四个位置开始往后走到第16个位置结束
0x80 + x是选择开始位置
0x80 + x + i从开始位置开始往后走,一直到第16个位置结束
c
lcd1602_write_cmd(0x80 + 0x40 + x + i - 16);
0x80是起始位置地址,0x40是1602的第二行的开始位置
0x80 + 0x40是1602第二行第一个位置
0x80+0x40+x是1602第二行第x+1位置,比如x是3,那么就是第二行第四个位置作为开始位置
i - 16是当i遍历到16的时候,i是从0开始的,0表示第一个字符,如果i是16的话,那么表示的是第17个字符,我们知道1602一行最多只有16个,如果超过16个那么将剩余的字符放在1602的第二行位置上,如果i此时是16了,那么结果就是16 - 16等于0
0x80 + 0x40 + x + i - 16
意思是第二行第x+1位置作为起始位置,然后往后遍历每一个字符,i是16就是第一个字符,i是17是第二个字符
最后执行的顺序是:先找到位置,然后将数据存储到该位置里面去
c
if(i < 16 - x)
lcd1602_write_cmd(0x80 + x + i);
else
lcd1602_write_cmd(0x80 + 0x40 + x + i - 16);
//写入数据
lcd1602_write_data(*str);
因为1602内部是由80个字节DDRAM组成,这里的找位置就是找到哪一个DDRAM存储空间,然后将数据存储到该存储空间里面去
3.5 单个字符显示
c
//单个显示字符
void lcd1602_show_data(u8 x, u8 y, u8 dat)
{
if (x > 15 || y > 1) return;
if (y < 1)
{
lcd1602_write_cmd(0x80 + x);
}
else
{
lcd1602_write_cmd(0x80 + 0x40 + x);
}
lcd1602_write_data(dat + 0x30);
}
这里的代码跟3.4一样唯一不一样的是写数据时候,dat + 0x30
dat + 0x30
这里的0x30是'0'的十六进制数,dat转换成ASCII对应的字符,比如dat是1需要转换成'1',这种字符1。
3.6 代码整合
main.c
c
#include "public.h"
#include "lcd1602.h"
void main()
{
lcd1602_init();
lcd1602_show_string(1,0,"hello world");
lcd1602_show_string(1,1,"123456789");
while(1)
{
}
}
public.c
c
#include "public.h"
void delay_10us(u16 us) {
while(us--);
}
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
public.h
c
#ifndef _public_H
#define _public_H
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 us);
void delay_ms(u16 ms);
#endif
LCD1602.c
c
#include "lcd1602.h"
//写命令
void lcd1602_write_cmd(u8 cmd)
{
LCD1602_RS = 0; //低电平写命令
LCD1602_WR = 0;
LCD1602_EN = 0;
LCD1602_DATAPORT = cmd;
delay_ms(1);
LCD1602_EN = 1;
delay_ms(1);
LCD1602_EN = 0;
}
//写数据
void lcd1602_write_data(u8 dat)
{
LCD1602_RS = 1; //高电平写数据
LCD1602_WR = 0;
LCD1602_EN = 0;
LCD1602_DATAPORT = dat;
delay_ms(1);
LCD1602_EN = 1;
delay_ms(1);
LCD1602_EN = 0;
}
//初始化1602
void lcd1602_init(void)
{
lcd1602_write_cmd(0X38); //设置1602 8位数据总线 2行 每一个数据是5*7点阵
lcd1602_write_cmd(0x0C); //设置1602 开启显示功能 是否使用光标 光标是否闪烁
//这里设置的不使用光标 如果设置不使用光标 光标闪烁设置0和1无所谓,这里设置0
lcd1602_write_cmd(0X06); //设置光标移动方向和显示屏移动
//这里每当写入一个数据后,光标后移动一位,以及屏幕整体不动进行设置
lcd1602_write_cmd(0X01); //清屏指令设置
}
//清屏
void lcd1602_clear(void)
{
lcd1602_write_cmd(0x01);
}
//在指定的坐标位置显示字符
//x: 0-15
//y: 0-1
void lcd1602_show_string(u8 x, u8 y, u8* str)
{
u8 i = 0;
if (x > 15 || y > 1) return;
if (y < 1) //第一行
{
while((*str) != '\0')
{
//找到需要写入的位置
if(i < 16 - x)
lcd1602_write_cmd(0x80 + x + i);
else
lcd1602_write_cmd(0x80 + 0x40 + x + i - 16);
//写入数据
lcd1602_write_data(*str);
str++;
i++;
}
}
else //第二行
{
while((*str) != '\0')
{
//找到需要写入的位置
if(i < 16 - x)
lcd1602_write_cmd(0x80 + 0x40 + x + i); //第二行
else
lcd1602_write_cmd(0x80 + x + i - 16); //第一行
//写入数据
lcd1602_write_data(*str);
str++;
i++;
}
}
}
//单个显示字符
void lcd1602_show_data(u8 x, u8 y, u8 dat)
{
if (x > 15 || y > 1) return;
if (y < 1)
{
lcd1602_write_cmd(0x80 + x);
}
else
{
lcd1602_write_cmd(0x80 + 0x40 + x);
}
lcd1602_write_data(dat + 0x30);
}
LCD1602.h
c
#ifndef _lcd1602_H
#define _lcd1602_H
#include "public.h"
sbit LCD1602_WR = P2^5;
sbit LCD1602_RS = P2^6;
sbit LCD1602_EN = P2^7;
#define LCD1602_DATAPORT P0
//写命令
void lcd1602_write_cmd(u8 cmd);
//写数据
void lcd1602_write_data(u8 dat);
//初始化1602
void lcd1602_init(void);
//清屏
void lcd1602_clear(void);
//在指定的坐标位置显示字符串
//x: 0-15
//y: 0-1
void lcd1602_show_string(u8 x, u8 y, u8* str);
//单个显示字符
void lcd1602_show_data(u8 x, u8 y, u8 dat);
#endif
4.实验现象


c
lcd1602_show_string(1,0,"hello world");
lcd1602_show_string(1,1,"123456789");
在main函数调用这两行函数
第一个函数x是1,y是0,字符串是"hello world"
y是行,x是列
第一行第二列位置开始显示字符串"hello world"
第二个函数x是1,y是1,字符串是"123456789"
y是行,x是列
第二行第二列位置开始显示字符串"123456789"