设计与开发

1602a怎么接单片机 第七课 控制液晶屏LCD1602《中学生C51单片机易学实战入门教程》

小编 2024-11-23 设计与开发 23 0

第七课 控制液晶屏LCD1602《中学生C51单片机易学实战入门教程》

实验准备

课程内容

第七课 控制液晶屏LCD1602

实验准备:

LCD1602 面包板 杜邦线

电阻:10k 8只 或排阻(用于P0上拉)

(或直接使用完整的开发板)

课程内容:

一、 原理图与接线

这里分析下 几个接口信号 V0、RS、RW、EN 表示的意义:

3脚:V0,液晶显示偏压信号,用于调整LCD1602的显示对比度,一般会外接电位器用以调整偏压信号,注意此脚电压为0时可以得到最强的对比度。

  4脚:RS,数据/命令选择端,当此脚为高电平时,可以对1602进行数据字节的传输操作,而为低电平时,则是进行命令字节的传输操作。命令字节,即是用来对LCD1602的一些工作方式作设置的字节;数据字节,即使用以在1602上显示的字节。值得一提的是,LCD1602的数据是8位的。

  5脚:R/W,读写选择端。当此脚为高电平可对LCD1602进行读数据操作,反之进行写数据操作。

  6脚:E,使能信号(LCDE),其实是LCD1602的数据控制时钟信号,利用该信号的上升沿实现对LCD1602的数据传输。

  7~14脚:8位并行数据口,使得对LCD1602的数据读写大为方便。

还有就是在单片机开发板上的接线:数据线接P0,控制线用P2中的三个IO

sbit LCD_RS = P2^6;

sbit LCD_RW = P2^5;

sbit LCD_EP = P2^7;

二、 底层操作

写命令 RS=L,RW=L,D0—D7=命令,EN=高脉冲 H

写数据 RS=H,RW=L,D0—D7=数据,EN=高脉冲H

三、 时序图

 

这节课引入时序图,其他器件类似,只要看懂时序图,就可以通过编程轻松控制这些器件按自己的需求工作,注意时间轴从左往右。

我们先不读出它的数据的状态或者数据本身。所以只需要看两个写时序:

  ① 当我们要写指令字,设置LCD1602的工作方式时:需要把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

  ② 当我们要写入数据字,在1602上实现显示时:需要把RS置为高电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。

  发现了么,写指令和写数据,差别仅仅在于RS的电平不一样而已。

操作步骤:(要对照时序图)

1) RS 确定 写数据还是命令

2) RW写模式 给0

3) P0 放数据或命令,延时5微秒

4) EN 给 1 延时5微秒 再给0 (即是给了脉冲)

这个表的命令也不需要记,在下面例程中LCD初始化部分就有厂家提供的代码.

还有下表是控制操作需要消耗的时间:ns表示纳秒

 

四、 按时序图编程

一个 _nop_(); 大约1微秒

void lcd_cmd(BYTE cmd)

{ // 写入指令数据到LCD

LCD_RS = 0;

LCD_RW = 0;

LCD_EP = 0;

P0 = cmd;

_nop_();_nop_();_nop_();_nop_();_nop_();

LCD_EP = 1;

_nop_();_nop_();_nop_();_nop_();_nop_();

LCD_EP = 0;

}

void lcd_wdat(BYTE dat)

{ //写入字符显示数据到LCD

LCD_RS = 1;

LCD_RW = 0;

LCD_EP = 0;

P0 = dat;

_nop_();_nop_();_nop_();_nop_();_nop_();

LCD_EP = 1;

_nop_();_nop_();_nop_();_nop_();_nop_();

LCD_EP = 0;

}

void lcd_init()

{ //LCD初始化设定

lcd_cmd(0x38); //16*2显示,5*7点阵,8位数据

lcd_cmd(0x0c); //显示开,关光标

lcd_cmd(0x06); //移动光标

lcd_cmd(0x01); //清除LCD的显示内容

}

BYTE code dis1[] = {" WELCOME TO "}; //要放最前面定义

BYTE code dis2[] = {" My C51 "};//要放最前面定义

main()

{

BYTE i;

lcd_init(); // 初始化LCD

delay(10);

while(1)

{

lcd_wcmd(0x06); //向右移动光标

lcd_ wcmd (0x80); //设置显示位置为第一行的第1个字符

i = 0;

while(dis1[ i ] != '\0') // \0 是C语言中字符串最后一个字符

{ //显示字符"WLCOME TO"

lcd_wdat(dis1[ i ]);

i++;

}

lcd_ wcmd (0x80+0x40); //设置显示位置为第二行第1个字符

i = 0;

while(dis2[ i ] != '\0')

{

lcd_wdat(dis2[ i ]); //显示字符" My C51"

i++;

delay(30); //控制两字之间显示速度

}

}

}

可以修改程序 让向左显示 ,或者移出移入

可以在在程序 中 需要的位置加入 延时 让数据稳定

五、增补C语言基础--数组

简单理解:数组是同种类型元素的集合。(特别注意:同种类型)

1. 一维数组定义

int a[10];

这样我们便定义了一个数组a,它分配10个int类型空间。

2.数组的初始化

例程中:

BYTE code dis1[] = {" WELCOME TO "};

定义了一个类型为 BYTE code 的数组,同时做初始化,这数组的各个元素都是一个字符,其中有空格,字母.

3.数组元素的访问

访问数组中的元素可以采用数组名加下标的方式,下标是从0开始,C语言并不检查数组下标是否越界,所以在访问数组中的元素时需要注意,需要对数组下标做判断,防止访问数组越界。

例子:

int a[10];

int i;

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

{

a[i] = i + 1;

}

至于二维数组,简单可理解为一个XX行YY列的表格,本教程现时还没有用到,所以暂时不作详解.

透彻理解液晶显示模组LCD1602指令集与驱动编程(1)

LCD1602可以说是大多数单片机工程师了解液晶显示的入门级模组,其显示原理与其它很多显示模组也是相似的,今天我们就来详细讨论一下它的指令集。所谓模组的指令集,本质上是该模组使用的控制芯片的指令集,本文主要讨论基于HD44780芯片 的LCD1602。

其实在博客园的博文中,我已经整理了一篇关于LCD1602的文章(原作者已不可考),从技术角度来讲,这篇文章写得还是不错的,该讨论的地方都涉及到了,对LCD1602显示有兴趣的读者可以去阅读一下。但是大家可能都知道,曾几何时,某人曾经对兄弟夸了海口:要说写技术文章,我谁也不服(此剧情纯属虚构,如有雷同,实属巧合,哈哈~~)!所以我决定百尺竿头更进一步,使用另一种方式来探讨它们,Let's Go Go Go, Fire in Hole,不好意思,走神了。

为了本文的完整性,我们简单介绍一下HD44780中DDRAM的组织方式,如下图所示:

DDRAM(Display DataRAM)即“显示数据随机存取存储器”,一般我们简称为“显存”,简单的说,你往显存中写入什么,屏幕上就会显示什么。显示位置(Display position)表示DDRAM地址对应的屏幕位置。例如,显示位置1(屏幕左上角)对应DDRAM地址0x00(当然,这只是默认情况下 )。

HD44780包含80个显存地址(第一行0x00~0x27、第二行0x40~0x67),也就意味可以显示最多80个字符。但是,我们使用的LCD1602只能显示2行,每行16个字符。换句话说,默认情况下 ,它只使用到了32个DDRAM地址(第一行0x00~0xF、第二行0x40~0x4F),相应的DDRAM地址与屏幕对应关系如下图所示(注意:两行DDRAM地址不是连续的 )。

例如,你想在LCD左上角显示内容,就应该把数据写入到DDRAM地址0x00中,如果想在LCD右下角显示内容,应该把相应的数据写入到DDRAM地址0x4F中。总之,液晶显示屏上的内容与DDRAM地址是一一对应的。

当然,我们往DDRAM中写入数据是字模的地址 (而不是字模本身 ),具体屏幕上显示什么取决于字模地址中对应的字模。HD44780芯片已经预定义了一些字模,它们保存在一个称为CGROM(Character Generator ROM,字符生成只读存储器)的地方,简单的说,CGROM就是一个字库,相应的字模如下图所示(当然,还有一个CGRAM,它允许用户自定义字模,后续有机会再讨论)。

使用CGROM中预定义的字模非常简单,只需要把字模对应的地址写入到DDRAM即可。例如,你要显示小写字母“j”,我们就应该写入0b0110_1010(0x6A),其中0110表示高4位地址(Upper 4 Bits),1010表示低4位地址(Lower 4 Bits)。

好的,我们已经知道如何确定字模地址,那怎么来定位DDRAM地址呢?总不能乱写一通吧!HD44780内部有一个地址计数器(AddressCount, AC ),它保存的就是DDRAM(或CGRAM)的地址,我们通过指令就可以控制具体访问的DDRAM地址。

咱们来看看HD44780数据手册定义的指令集,后续的单条指令截图都可以从这里查到,如下图所示:

首先我们来看看“功能设置(Function Set)”指令,它用来设置与硬件相关的配置,功能设置不当可能会导致数据传输或显示不正常,所以“功能设置”指令通常也是发送给LCD1602的第一条指令,其中包含DL、N、F三个配置位,如下图所示:

DL 位(Data Length)选择数据总线的宽度为4位(DL=0)还是8位(DL=1),一般我们常用的还是8位总线。

N 位(Number)表示一行(N=0)还是两行(N=1)显示(它们对应的DDRAM地址是不一样的,有兴趣可以参考数据手册查阅一行显示的DDRAM组织方式),LCD1602当然应该设置为2行显示。

F 位(Font)表示显示的字体为5x8点阵(F=0)还是5x10(F=1),两行显示下只能显示5x8点阵,下图左侧给出了两种字体的区别(包含光标位置,右侧是光标闪烁时的状态转换)

我们决定使用8位数据总线给LCD1602发送数据,相应的指令应该为“0b11_1000(0x38) ”。

然后我们可以使用显示开关控制(Display on/offcontrol) 指令,之所以紧赶慢赶地先讨论它,是因为只要正确使用该指令,就可以打开显示并开启(闪烁)光标。在实际硬件调试时,能打开光标就意味着硬件的连接正常,且单片机往模组中写入的数据被正常接收(即写数据的时序正确),至此显示模组的驱动过程基本上已经完成了一半,接下来就是逐个指令调试的过程了。

显示开关控制指令可以设置D、C、B三位,HD44780数据手册对该指令的详细描述如下:

D位 (Display)是显示开关控制位,当D=1时显示开启,当D=0时显示关闭。当然,该位状态并不影响DDRAM中已经写入的数据,如果你反复开启与关闭显示,DDRAM中的内容仍然是不变的,因为本质上它只是控制液晶屏驱动时序是否生成。

C位 (Cursor)表示是否显示光标,当C=1时显示,当C=0时不显示光标。B位 (Blink)表示光标是否闪烁,当B=1时表示闪烁,当B=0时不闪烁。

假设我们需要打开显示,且开启光标闪烁,需要给HD44780的指令是什么呢?我们把显示开关控制(Display on/off control)指令重新剪贴如下:

打开显示需要设置D=1,显示光标需要设置C=1,而让光标闪烁需要设置B=1,也就是说,我们需要给HD44780发送指令“0xF ”。我们来看看VisualCom软件平台相应的仿真效果,如下图所示

VisualCom软件平台中“内存”与“寄存器”窗口中的数据取决于具体的调入元器件类型,一般的显示控制芯片(这里是HD44780)都会有,而像LED、数码管、按键之类器件则无。VisualCom软件平台有一个非常实用的功能,就是预置数据 ,它可以给当前选择的器件预置一些数据或命令,当你运行仿真之后,器件会先执行预置数据。

我们先调入“LCD1602”仿真器件,右击后在弹出的快捷菜单中选择“预置数据”项即可打开如下图所示对话框。

对话框中有一个表格,你可以插入想要的数据行,“类型 ”栏中可以是数据命令 ;“附加栏 ”是扩展项,对于HD44780是无效的;“十进制 ”与“十六进制 ”表示插入的具体数据或命令,两栏的数据完全一样,你往十进制写入15,十六进制中就会显示F,反之亦然,这可以方便不同的进制数据输入的场合;“自定义备注 ”栏可以为你插入的行做注释。

为了插入数据或命令行,你可以选择左下角的“插入数据”或“插入命令”按钮插入数据行,它们会在表格的结尾插入,你也可以右击后选择相应的选项,它可以在你点击的某行上方插入一行。当然,也可以对数据行进行移动、删除等操作,此处不再赘述

我们先插入一条“功能设置指令”(0x38 ),再插入了一条“显示开关控制指令”(0xF ),然后点击“单步运行”按钮,就可以看到液晶显示模组的左上角出现了一个闪烁的光标。同时我们注意到,“寄存器窗口”中的B、C、D位均为1。光标的位置由地址计数器(AC)决定 ,由于AC =0,所以光标出现在左上角。

执行“0xF ”指令后还显示了两行字符“join weixin mp XXXXX ”,我们可以查看“内存窗口”中对应的字模地址。例如,0x01地址中数据为0x6A,也就是小写字母“j”的字模地址,其它依此类推。我们买到的真实LCD1602模组当然不会显示这两行字,然而即便如此,我们通常也会习惯使用一条清屏指令(Clear Display) 清除屏幕的显示内容,因为上电之后DDRAM中的数据可能是乱码,相应的指令如下所示:

清屏,顾名思义,一旦执行该指令,屏幕上不会有任何内容显示。实际上,清屏指令把所有DDRAM地址中的数据都设置为0x20。

有些人可能会想:为什么不全部设置为0x00呢?因为前面已经提过,DDRAM中的数据代表的是字模地址 ,而不是字模本身 。我们看看前面的CGROM字模表,0x20(0b0010_0000)恰好对应一个空白的字模(实际上,0x20就是空格的ASCII码),这样也就可以清除屏幕显示。

我们在之前的预置数据后再添加了一条指令“0x1 ”,单步运行后的效果如下图所示:

可以看到,“内存窗口”中的有DDRAM地址的数据全部都修改为0x20,但是原来光标状态还是不变的,该显示的显示,该闪烁的还是闪烁,因为光标不属于显示内容,只不过其位置总会回到左上角(如果原来没在左上角的话),数据手册对此已经明确说明,如下图所示:

这段说明中还提到了I/D 位(Increment/Decrement)与S 位(Shift),这就要涉及到另一条“进入模式设置(Entry mode set) ”,如下图所示。

前面我们不是说过,想往哪个DDRAM地址写数据就需要先设置AC 吗?现在我们要写一行16个字符,如果每写一个字符都要使用指令设置一下DDRAM地址,是不是很麻烦?HD44780允许我们往(从)DDRAM地址写(或读)数据后,将AC 自动加1(I/D=1)或减1(I/D=0),这样如果你要写一行字符,只需要确定首地址就可以了,是不是很方便?由于光标的位置取决于AC ,如果光标显示已经打开,当你往DDRAM连续写入字符时,光标位置也会随之移动。

现在我们要从左上角开始写入字符串“dzzzzcn”,首先从CGROM字模表中找到小写字母“d”、“z”、“c”、“n”对应的字模地址分别为“0x64 ”、“0x7A ”、“0x63 ”、“0x6E ”、,然后在VisualCom软件中再接着添加7个预置数据,即“0x64”、“0x7A”、“0x7A”、“0x7A”、“0x7A”、“0x63”、“0x6E”,如下图所示:

运行后的效果如下图所示:

有人可能会想问:没看到你使用DDRAM地址设置指令呀?也没有使用“进入模式设置”指令设置地址增加模式,怎么它就会从左上角(0x00)开始写起呢?因为我们已经使用的清屏指令,它会把AC 清零,并且它还会将I/D 位设置为1(地址增加模式)。

S位 用来控制移屏功能的开启与否。移屏是个神马东西?其实跟卷屏差不多,只不过卷屏通常是显示内容上下卷动,而HD44780只有两行,它的移屏方向要么左(I/D=1)要么向右(I/D=0),你想要开启它,只要将S位设置为1即可,数据手册说明如下:

注意该段说明中有句话:如果S=1,看起来光标没有移动但屏幕移动了 。这是什么意思呢?我们仿真一下不就知道了,将预置数据修改如下:

我们只是在写数据前插入了一条“进入模式设置”指令(0x5 ),它打开了移屏功能,并且将I/D设置为0。也就是说,每往DDRAM写一个数据,地址会自减1,而且会往右移屏。

我们来看看相应的仿真效果,如下图所示。

运行结果似乎有点耐人寻味?怎么会是这样的呢?其实并没有错,因为我们设置了地址自减模式,而清屏后的AC =0,那么你再写一个数据,它减到哪里去了?就跳到第一行DDRAM的尾地址0x27(而不是0xF)。我们前面已经提过,LCD1602只使用了32个DDRAM地址(第一行0x00~0xF、第二行0x40~0x4F),所以在正常情况下,当你往DDRAM地址0x27写入字模地址时,屏幕上是不会显示相应的字模,对不对?

但是由于你开启了右移屏指令,当你写第一个字母d的时候,AC 指向了DDRAM地址0x27,同时往右移了一次屏,所以此时屏幕最左侧对应的DDRAM地址就是0x27(第一行)与0x67(第二行),而不再是原来的0x0与0x40,更不是正常情况下LCD1602最右侧对应的DDRAM地址0xF与0x4F。

当你全部写完“dzzzzcn”字符串后,光标所在的位置(AC )就是0x21。也就是说,你写7个字符的同时也往右移了7次屏。看到没有,光标原来的位置并没有改变就是这个意思。

如果我们把地址模式改为自加模式(“进入模式指令”为0x7 ),写入同样的数据会出现什么结果呢?自加模式下为左移屏,每写一次数据左移一次,所以最后的结果应该是:从显示屏上来看,相当于什么都没写 。我们来看看仿真的结果,如下图所示:

好像跟清屏后的效果一样呀!但是请注意,现在的AC值为0x7 ,从“内存窗口”可以看到,DDRAM地址0x00~0x07中还是写入了“dzzzzcn”的字模,只不过由于写数据的同时往左移了7次屏,所以看起来好像什么都没写一样。

好的,剩下的指令我们后续有机会再来讨论吧,么么哒~~

相关问答

1602 单片机 引脚怎么连接?

1602对应上面每一只脚都有名字的,你上网找一下就知道了,然后你可以看到你的程序刚开始的的方都有因骄傲的宏定义了,按照那个定义和单片机对应接上就可以了。记...

lcd 1602接单片机 要多大电阻?

lcd1602接单片机需要一个10kΩ的电阻。LCD1602是一种常用的字符型液晶显示屏,它需要通过单片机来控制显示内容。在连接LCD1602和单片机时,需要使用一个10kΩ的...

单片机 显示模式设置?

这个是1602内部结构决定的,你只需要在初始化的时候先设置三次显示,然后再设置你的其他要求。芯片厂家推荐的用法:INT:MOVA,#30HMOVDATR,#CW_ADDMOVR2...

51 单片机 1602 与51 单片机 是怎么传输信号的?

HOT51开发板使用的是STC8051CPU,具备完整的P0,P1,P2口功能;1602液晶使用8位数据线,E,RW,RS分别连接关系为:8位数据线接P1口,E接P2.0,RW,接P2.1,RS接P...

单片机1602 一个读忙程序的问题,请大神赐教?

/*busy_flag变量是bit型,位类型的;其结果只能是0和1;(P0&0x80);---P0口是一个8位的,先对P0=0XFF;转换成二进制按位与11111111&1...

C51 单片机 中,如何把一int型形参中的数值显示在 1602 液晶屏上?

在C51单片机中,要将一个int型形参中的数值显示在1602液晶屏上,可以通过以下步骤进行操作:1.首先,连接好C51单片机和1602液晶屏。确保液晶屏的VCC(正电源)...

请问如何用STC 单片机 直接驱动段码LCD,具体那些型号,各位高手可否提供方法与参考代码?

1602吧,我们做过那个,挺简单的,随便一本单片机书上都有他的代码,汇编写的,也有c的,我这有一段它的控制显示代码,C的,不短1602吧,我们做过那个,挺简单的,随便...

lcd 1602 调试方法?

下面尝试使用51单片机制作一个密码锁,尝试使用矩阵键盘,按键按下后,return对应的数字(0123456789),之后将数字赋值给lcd的写数据函数,然后编译之后,屏幕...

51 单片机 字符液晶屏(LMC 1602 )输出端RS,RW还有E分别都有什么作用?

从左向右,1,2,3是电源和亮度(不同的1602型号对应也不同),4,5,6,是rs,rw,e,一般是这样的,就算接错了,在单片机里面重定义就行了从左向右,1,2,3是电源和亮度(不...

51 单片机 , 1602 动态显示时钟,有独立按键(3个k1,k2,k3)分别控...

[最佳回答]我这又一个参考程序,是用郭天祥的TX-1C开发板写的,有3个按键,调节光标,时间加,时间减.引脚方便可以根据自己的开发板更改,其他程序内容不变.希望我...

猜你喜欢