by Jan Svenungson <jan.svenungson(at)linux.nu>
关于作者:
Jan从1996年就开始使用GNU/Linux,可是只遇到了2次突然的重启(当然,电源故障引起的可没有算)
目录:
|
理解HD44780兼容型LCD显示屏
摘要:
这篇文章试图使你能对HD44780兼容型LCD显示屏略知一二。
我们将把它连接到并口,并且编写简单的程序,以对一个叫做LCDInfo的小程序进行参考调用。
你将不仅学到如何连接显示屏,运行程序并获得简单显示,更重要的是你将懂得如何使硬件设备如你所愿的工作。
简要介绍
首先,你必须准备一些相关的软硬件。而我假设你已经拥有了一台运行着GNU/Linux系统——以便能够使用gcc和glibc,并且有着标准并行接口(也就是串口)的电脑。
此外,你还需要一块HD44780兼容型LCD显示屏,用来连接到电脑的并口,为了调节对比度,还应该在它们之间联接一个电位计。要想驱动这个系统,仅仅依靠并口的电流是不够的,你需要从系统中获得额外的能量,最好就是使用系统中标准的+5V接口(即用于驱动硬盘,光驱等等的电源接口)。
当你连接好了LCD显示屏,你就需要知道如何让它工作。其他的文章总喜欢把这一部分略掉,但我希望通过揭示其内部的工作原理来帮助你编程。
最后一件事是如何让这个显示单元显示一些有用的东西。作为参考,我将使用一个叫做LCDInfo的小程序,它支持HD44780大多数的特性却又不会显得过分复杂。这个程序仍处于开发之中,我只是在空闲时侍弄它。如果你没有编写C程序的经验,或许你需要粗略的学习一下。我将假设你正好和我一样是个C语言的新手。
如何连接
让我们先看看LCD各个的引脚及其定义。
Pin 1为VSS,直接连接GND。
Pin 2为VDD,接+5V作为电源供应。
Pin 3为VLC,连接到电位计,用来调节显示的的对比度。
Pin 4为RS,显示屏依靠这个引脚来分辨接受到的是指令还是数据。
Pin 5是R/W,控制着LCD是 发送或是接收。
Pin 6是Enable,当出现一个从低到高再到低的脉冲,LDC将读取Pin4,5以及7-14。其中Pin 7-14是数据总线被称为DB0-DB7,是LCD接受到的主要数据比特并控制着信息在显示屏上写入的位置和内容。
Pin 15和16为显示屏提供背光。其中Pin 15串接一个3.8欧的电阻到+5V,而Pin 16则简单的连接GND。
有关如设备和打印口的具体连接,可参考右边的电路原理图。我已经尽力使它清晰了,点击可以看到大图。
这个原理图只适用于需要对显示对比度进行调节的场合。而且我只是简单的把pin 3和1连接到了GND,就获得了不错的效果。如果你的室内有奇怪的光源,也许你需要考虑增加电位计。
当你从PC电源上获取电源时,请务必小心。如果接错了电线,你可能会将+12V的电源接到LCD系统上,烧坏整个系统。一般而言红色的电缆才是你需要的,而黄色的那根是+12V,黑的是GND。
如果把上述的工作都做好了,当你打开PC时,第一行(和第三行,如果存在的话)将是黒的。
LCD如何工作
在你作出指示之前,LCD系统是不会有任何动作的。直到它接收到一个先跃升再下降的enable脉冲(这需要我们将Enable引脚置高,等待一会儿之后再将该引脚置回低电平)。这时显示系统将开始读取并判断是否有指令或数据需要处理,然后判断是否将接受或者发送信息,最后判断针对这些数据比特是执行发送还是接受操作。
文章中我们不会从LCD端接受信息,所以R/W引脚始终都应被置低,表示写入。
除了打印字符时,RS pin都将置低,其它东西可以认为都是指令。
这使得有关显示的编程非常简单。
掌握了这些东西之后,我们就盘算着打开显示,并让它准备好接受信息。这些都将在初始化序列中得到执行,在此过程中将作出诸如使用“功能设定”来打开显示等操作。
你需要做的第一件事是从PC上连接出合适的电源线接到系统上,如果你还没做好,那就赶快。
接下来是“功能设定”,这取决于你所拥有的显示系统。
为了便于理解 ,我会详细解释功能设定中的相关操作。
DB2是字符字体位,在此设为low,表示5x7点阵。
DB3是显示线宽位,应该是高,表示双线。那么要用4线,又该怎么办呢?别担心,第一线和第三线在显存中是相同的,所以你仍需置高。
DB4是数据长度位,它决定了你使用4个还是8个数据位。如果你使用我的电路原理图,你应该将此位置高。
接下来是将DB5置高,以便告诉显示系统这才是真的“功能设定”指令,同时确定RS和R/W都被置低,并给一个先跃升再下降的enable脉冲。至于具体时间间隔还需要查阅说明书,我想显示之前的间隔应该只是毫秒级的,比我们需要的还要好些。
关于代码?What about the code?
在这儿我需要针对部分LCDInfo程序进行一下解释,以便你了解HD44780的接口是如何工作的。你可以在文章的末尾下载这个LCDInfo程序,也可以直接点击这里查看代码文件iolcd.c和lcdinfo.c。
我们现在所需要的就是前面提到过的C程序,那很容易的,请相信我。我会一步一步的解释那些代码,即使你是一个C的初学者也一定能明白。
首先,我们要预定义一些头文件和宏定义(具体信息请查看源文件)。接下来就是有趣的部分了。
#define D_REGISTER 0
#define I_REGISTER 2
#define WRITE_DATA 8
#define BASE 0x378
int main(void)
{
ioperm(BASE,3,1);
[CUT]
}
这是main函数中的第一个命令,它允许我们连接到并行接口,基址应该是0x378或者其他的某处,那个“3”表示我们要占用3个连续的地址空间0x378, 0x379
and 0x380,基本上就是整个打印端口了。
要占用3个地址空间是因为那个端口是被分成了数据,状态和控制3部分。对我们而言,这意味着必须先设定数据引脚,然后是控制引脚,我们不可能在一个命令中实现。
接下来对前面提到的函数进行定义。
void function_set(void)
{
outb(56, BASE);
这一步把DB引脚设定为5x7的点阵以及双线等等。
outb(I_REGISTER + WRITE_DATA, BASE + 2);
这里将RS和R/W引脚设定为指令模式以及写入模式。我定义了全局变量I_REGISTER和WRITE_DATA,并且分别等于2和8。
接下来是执行enable命令,通过一个电平的上升和下降使系统开始工作。
outb(ENABLE + I_REGISTER + WRITE_DATA, BASE + 2);
usleep(0);
outb(I_REGISTER + WRITE_DATA, BASE + 2);
}
这段代码只是简单的将enable引脚电平拉高,等待,再降低。至于usleep(0),并不是太理想,但我还没来得及为显示写出更好的时延子程序。
肯定有很多人会问为什么在代码中我把RS和R/W引脚打开了,却在上文中说应该将它们置低。这是因为引脚1,14和17号都是“硬件翻转”的,即如果打印端口认为引脚14是“关闭”时,引脚是高电平!
好了,我告诉过你这还算简单,对吧?
如何显示字符?
也许你也想对你的显示系统进行一些实践,比如说显示一下文本?没问题。
所需的程序(编写的指令)和显示一个字符的大同小异。我们只需要改变一下相关的变量。我们不想把RS设为指令模式,而是设为数据模式以便直接开始。这使得函数print_character()如下所示:
void print_character(int character)
{
outb(D_REGISTER + WRITE_DATA, BASE + 2);
outb(character, BASE);
outb(ENABLE + D_REGISTER + WRITE_DATA, BASE + 2);
usleep(0);
outb(D_REGISTER + WRITE_DATA, BASE + 2);
}
正如你所看到的,我们把"I_REGISTER"改成了"D_REGISTER",把"56"改成了"character",这是什么意思呢?看看说明书中有关字符编码的部分,你就会懂了。
我们只需要为相关的函数加入一个字符(由于采用的C语言,我们甚至不用麻烦的将它预定义为整数型),然后这个字符就会显示在显示屏上。很棒吧?
这就是LCD系统相关程序的框架了,根据你的应用而作些修改,它可以胜任诸如显示mem信息,显示激活的http连接或者其他的一些任务。有些例子在LCDInfo 程序中,它们将显示一些在GNU/Linux中的proc文件系统下可用的东西。
参考资料
对这篇文章发表评论
每篇文章都有各自的反馈页面。在这个页面里,您可以提交评论,也可以查看其他读者的评论:
2002-10-31, generated by lfparser version 2.25