LCD1602可以说是大多数单片机工程师了解液晶显示的入门级模组,其显示原理与其它很多显示模组也是相似的,今天我们就来详细讨论一下它的指令集。所谓模组的指令集,本质上是该模组使用的控制芯片的指令集,本文主要讨论基于HD44780芯片 的LCD1602。
其实在博客园的博文中,我已经整理了一篇关于LCD1602的文章(原作者已不可考),从技术角度来讲,这篇文章写得还是不错的,该讨论的地方都涉及到了,对LCD1602显示有兴趣的读者可以去阅读一下。但是大家可能都知道,曾几何时,某人曾经对兄弟夸了海口:要说写技术文章,我谁也不服(此剧情纯属虚构,如有雷同,实属巧合,哈哈~~)!所以我决定百尺竿头更进一步,使用另一种方式来探讨它们,Let’s Go Go Go, Fire in Hole,不好意思,走神了。
为了本文的完整性,我们简单介绍一下HD44780中DDRAM的组织方式,如下图所示:

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

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

好的,我们已经知道如何确定字模地址,那怎么来定位DDRAM地址呢?总不能乱写一通吧!HD44780内部有一个地址计数器(AddressCount, AC ),它保存的就是DDRAM(或CGRAM)的地址,我们通过指令就可以控制具体访问的DDRAM地址。
咱们来看看HD44780数据手册定义的指令集,后续的单条指令截图都可以从这里查到,如下图所示:


N 位(Number)表示一行(N=0)还是两行(N=1)显示(它们对应的DDRAM地址是不一样的,有兴趣可以参考数据手册查阅一行显示的DDRAM组织方式),LCD1602当然应该设置为2行显示。
F 位(Font)表示显示的字体为5×8点阵(F=0)还是5×10(F=1),两行显示下只能显示5×8点阵,下图左侧给出了两种字体的区别(包含光标位置,右侧是光标闪烁时的状态转换)

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

C位 (Cursor)表示是否显示光标,当C=1时显示,当C=0时不显示光标。B位 (Blink)表示光标是否闪烁,当B=1时表示闪烁,当B=0时不闪烁。
假设我们需要打开显示,且开启光标闪烁,需要给HD44780的指令是什么呢?我们把显示开关控制(Display on/off control)指令重新剪贴如下:


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

为了插入数据或命令行,你可以选择左下角的“插入数据”或“插入命令”按钮插入数据行,它们会在表格的结尾插入,你也可以右击后选择相应的选项,它可以在你点击的某行上方插入一行。当然,也可以对数据行进行移动、删除等操作,此处不再赘述
我们先插入一条“功能设置指令”(0x38 ),再插入了一条“显示开关控制指令”(0xF ),然后点击“单步运行”按钮,就可以看到液晶显示模组的左上角出现了一个闪烁的光标。同时我们注意到,“寄存器窗口”中的B、C、D位均为1。光标的位置由地址计数器(AC)决定 ,由于AC =0,所以光标出现在左上角。
执行“0xF ”指令后还显示了两行字符“join weixin mp XXXXX ”,我们可以查看“内存窗口”中对应的字模地址。例如,0x01地址中数据为0x6A,也就是小写字母“j”的字模地址,其它依此类推。我们买到的真实LCD1602模组当然不会显示这两行字,然而即便如此,我们通常也会习惯使用一条清屏指令(Clear Display) 清除屏幕的显示内容,因为上电之后DDRAM中的数据可能是乱码,相应的指令如下所示:

有些人可能会想:为什么不全部设置为0x00呢?因为前面已经提过,DDRAM中的数据代表的是字模地址 ,而不是字模本身 。我们看看前面的CGROM字模表,0x20(0b0010_0000)恰好对应一个空白的字模(实际上,0x20就是空格的ASCII码),这样也就可以清除屏幕显示。
我们在之前的预置数据后再添加了一条指令“0x1 ”,单步运行后的效果如下图所示:



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


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


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

但是由于你开启了右移屏指令,当你写第一个字母d的时候,AC 指向了DDRAM地址0x27,同时往右移了一次屏,所以此时屏幕最左侧对应的DDRAM地址就是0x27(第一行)与0x67(第二行),而不再是原来的0x0与0x40,更不是正常情况下LCD1602最右侧对应的DDRAM地址0xF与0x4F。
当你全部写完“dzzzzcn”字符串后,光标所在的位置(AC )就是0x21。也就是说,你写7个字符的同时也往右移了7次屏。看到没有,光标原来的位置并没有改变就是这个意思。
如果我们把地址模式改为自加模式(“进入模式指令”为0x7 ),写入同样的数据会出现什么结果呢?自加模式下为左移屏,每写一次数据左移一次,所以最后的结果应该是:从显示屏上来看,相当于什么都没写 。我们来看看仿真的结果,如下图所示:

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