51单片机LCD1602液晶屏显示

目录

  • 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"

相关推荐
泡泡糖的中文规格书3 小时前
STM32G030F6P6中文规格书开放获取(完整中英对照/ARM Cortex-M0+ MCU)
stm32·单片机·嵌入式硬件·pcb设计·硬件设计·中文数据手册
MARIN_shen3 小时前
Marin说PCB之电源PI仿真之PDN---DK值的影响
嵌入式硬件·硬件工程·信号处理·pcb工艺
正点原子4 小时前
《ESP32-S3使用指南—IDF版 V1.6》第十章 ESP32-P4存储器类型
单片机·物联网·嵌入式
Mao_Hui4 小时前
Unity3d实时读取Modbus RTU数据
开发语言·嵌入式硬件·unity·c#
吉哥机顶盒刷机7 小时前
晶晨芯片机顶盒与海思芯片机顶盒刷机区别详解
经验分享·嵌入式硬件·刷机
森利威尔电子-7 小时前
SL4011:2.7V-12V输入,12.8V输出高效率升压型DC-DC转换器
单片机·嵌入式硬件·集成电路·芯片·电源芯片
想搞嵌入式的小白7 小时前
LDO和DC-DC的异同
单片机·嵌入式硬件
EVERSPIN7 小时前
RGB显示驱动MCU单片机—CH643键盘应用方案
单片机·嵌入式硬件·mcu·计算机外设·mcu单片机
edjxj8 小时前
PFC电路学习
单片机·学习