EDN首页   博客首页 用户登陆  |  注册
aaa
发表于 2008/10/16 11:53:09

0

关于投票

(001)基于HD44780液晶芯片的16×2字符型液晶(1602)简介

从技术到FAE已有7个多月了,一直也没有再做什么具体的研发工作,由于工作需要,最近在写LCD1602的显示程序,发现自己真的笨了许多,很简单的一个程序我竞然搞了近一天才搞定,看来技术真的是不练不行啊。以后要注意了。

这是我找的相关资料,真的是感谢这位高人,也希望大家多多向他学习哈,现在转两篇文章过来,大家共同提高!

(001)基于HD44780液晶芯片的16×2字符型液晶(1602)简介


 

声明:本文内容选自《AVR单片机与CPLD/FPGA综合应用入门》及《smc 1602A LCM 使用说明书》,自用资料存档,请勿转载!否则因此引起的版权问题本人概不负责!

液晶显示器以其微功耗、小体积、使用灵活等诸多优点在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。液晶显示器通常可分为两大类,一类是点阵型,另一类是字符型。点阵型液晶通常面积较大,可以显示图形;而一般的字符型液晶只有两行,面积小,只能显示字符和一些很简单的图形,简单易控制且成本低。目前市面上的字符型液晶绝大多数是基于HD44780液晶芯片的,所以控制原理是完全相同的,为HD44780写的控制程序可以很方便地应用于市面上大部分的字符型液晶。

字符型LCD通常有14条引脚线(市面上也有很多16条引脚线的LCD,多出来的2条线是电源线VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样),定义如下表所示:

                        字符型LCD的引脚定义

┌────┬────┬────┬──────┬────────────┐
ㄧ 引脚号 ㄧ 引脚名 ㄧ  电平  ㄧ  输入/输出 ㄧ         作用           ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   1    ㄧ  Vss   ㄧ        ㄧ            ㄧ 电源地                 ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   2    ㄧ  Vcc   ㄧ        ㄧ            ㄧ 电源(+5V)              ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   3    ㄧ  Vee   ㄧ        ㄧ            ㄧ 对比调整电压           ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   4    ㄧ  RS    ㄧ  0/1   ㄧ    输入    ㄧ 0=输入指令             ㄧ
ㄧ        ㄧ        ㄧ        ㄧ            ㄧ 1=输入数据             ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   5    ㄧ  R/W   ㄧ  0/1   ㄧ    输入    ㄧ 0=向LCD写入指令或数据  ㄧ
ㄧ        ㄧ        ㄧ        ㄧ            ㄧ 1=从LCD读取信息        ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   6    ㄧ  E     ㄧ 1,1→0 ㄧ    输入    ㄧ 使能信号,1时读取信息, ㄧ
ㄧ        ㄧ        ㄧ        ㄧ            ㄧ 1→0(下降沿)执行指令   ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   7    ㄧ  DB0   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line0(最低位)  ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   8    ㄧ  DB1   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line1          ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ   9    ㄧ  DB2   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line2          ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ  10    ㄧ  DB3   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line3          ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ  11    ㄧ  DB4   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line4          ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ  12    ㄧ  DB5   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line5          ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ  13    ㄧ  DB6   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line6          ㄧ
├────┼────┼────┼──────┼────────────┤
ㄧ  14    ㄧ  DB7   ㄧ  0/1   ㄧ  输入/输出 ㄧ 数据总线line7(最高位)  ㄧ
└────┴────┴────┴──────┴────────────┘

HD44780内置了192个常用字符,存于字符产生器CGROM(Character Generator ROM)中,另外还有几个允许用户自定义的字符产生RAM,称为CGRAM(Character Generator RAM)。下图说明了CGROM和CGRAM与字符的对应关系(由于本书中未用到自定义特殊字符的功能,所以本节不对CGRAM作详细介绍。以下如未特别说明,则"字符码"指CGROM的字符号,"地址"指DDRAM的地址)。

字符码0x00~0x0F为用户自定义的字符图形RAM(对于5X8点阵的字符,可以存放8组,5X10点阵的字符,存放4组),0x20~0x7F为标准的ASCII码,0xA0~0xFF为日文字符和希腊文字符,其余字符码(0x10~0x1F及0x80~0x9F)没有定义。



除了CGROM和CGRAM外,LCD内部还有一个DDRAM(Display Data RAM),用于存放待显示内容,LCD控制器的指令系统规定,在送待显示字符代码的指令之前,先要送DDRAM的地址(即待显示的字符显示位置)。16×2的字符型LCD的DDRAM地址与显示位置的对应关系如下:


                DDRAM地址与显示位置的对应关系

╭┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╮
┊                                                                ┊
┊00H 01H 02H 03H 04H 05H 06H 07H 08H 09H 0AH 0BH 0CH 0DH 0EH 0FH ┊
┊                                                                ┊
┊40H 41H 42H 43H 44H 45H 46H 47H 48H 49H 4AH 4BH 4CH 4DH 4EH 4FH ┊
┊                                                                ┊
╰┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╯

如果读者到现在对DDRAM的用法还是很迷惘,希望下面这个简单的例子能帮助读者理解。假设要在第1行第2列写入字符"A",这时先写入第1行第2列对应的DDRAM的地址:01H(参见上图),然后再往DDRAM中写入"A"的字符码0x41(参见字符与字符码对照表),这样LCD的第1行第2列就会出现字符A了。也就是说,DDRAM的内容对应于把要显示的字符地址,而DDRAM的地址就对应于显示字符的位置。总而言之,希望在LCD的某一特定位置显示某一特定字符,一般要遵循"先指定地址,后写入内容"的原则;但如果希望在LCD上显示一串连续的字符(如单词等),并不需要每次写字符码之前都指定一次地址,这是因为液晶控制模块中有一个计数器叫地址计数器AC(Address Counter)。地址计数器的作用是负责记录写入DDRAM数据的地址,或从DDRAM读出数据的地址。该计数器的作用不仅仅是"写入"和"读出"地址,它还能根据用户的设定自动进行修改。比如,如果规定地址计数器在"写入DDRAM内容"这一操作完成后自动加1,那么在第1行第1列定写入一个字符后,如果不对字符显示位置(DDRAM地址)重新设置,再写入一个字符,则这个新的字符会出现在第1行第2列。

那么如何对DDRAM的内容和地址进行操作呢,下面是HD44780的指令集及其设置说明,请浏览该指令集,并找出对DDRAM的内容和地址进行操作的指令。


清屏指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /ms  ㄧ
├──────┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼───┤
ㄧ    清屏    ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧ 1.64 ㄧ
└──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┘
功能:<1> 清除液晶显示器,即将DDRAM的内容全部填入"空白"的ASCII码20H;
      <2> 光标归位,即将光标撤回液晶显示屏的左上方;
      <3> 将地址计数器(AC)的值设为0。


光标归位指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /ms  ㄧ
├──────┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼───┤
ㄧ  光标归位  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧ X  ㄧ 1.64 ㄧ
└──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┘
功能:<1> 把光标撤回到显示器的左上方;
      <2> 把地址计数器(AC)的值设置为0;
      <3> 保持DDRAM的内容不变。


进入模式设置指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼───┤
ㄧ进入模式设置ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧI/D ㄧ S  ㄧ  40  ㄧ
└──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┘
功能:设定每次定入1位数据后光标的移位方向,并且设定每次写入的一个字符是否移动。参数设定的
      情况如下所示:
      位名    设置
      I/D     0=写入新数据后光标左移        1=写入新数据后光标右移
      S       0=写入新数据后显示屏不移动    1=写入新数据后显示屏整体右移1个字符


显示开关控制指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼───┤
ㄧ显示开关控制ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧ D  ㄧ C  ㄧ B  ㄧ  40  ㄧ
└──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┘
功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下:
      位名    设置
       D      0=显示功能关     1=显示功能开
       C      0=无光标         1=有光标
       B      0=光标闪烁       1=光标不闪烁


设定显示屏或光标移动方向指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼───┤
ㄧ设定显示屏或ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧS/C ㄧR/L ㄧ X  ㄧ X  ㄧ  40  ㄧ
ㄧ光标移动方向ㄧ    ㄧ    ㄧ    ㄧ    ㄧ    ㄧ    ㄧ    ㄧ    ㄧ    ㄧ    ㄧ      ㄧ
└──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┘
功能:使光标移位或使整个显示屏幕移位。参数设定的情况如下:
      S/C     R/L      设定情况
      0       0        光标左移1格,且AC值减1
      0       1        光标右移1格,且AC值加1
      1       0        显示器上字符全部左移一格,但光标不动
      1       1        显示器上字符全部右移一格,但光标不动


功能设定指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┼──┼──┼──┼──┼──┼──┼───┤
ㄧ  功能设定  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧ DL ㄧ N  ㄧ F  ㄧ X  ㄧ X  ㄧ 40   ㄧ
└──────┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴───┘
功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:
      位名    设置
      DL      0=数据总线为4位        1=数据总线为8位
      N       0=显示1行              1=显示2行
      F       0=5×7点阵/每字符      1=5×10点阵/每字符


设定CGRAM地址指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┼──┴──┴──┴──┴──┴──┼───┤
ㄧ设定CGRAM   ㄧ 0  ㄧ 0  ㄧ 0  ㄧ 1  ㄧ     CGRAM的地址(6位)             ㄧ  40  ㄧ
ㄧ   地址     ㄧ    ㄧ    ㄧ    ㄧ    ㄧ                                  ㄧ      ㄧ
└──────┴──┴──┴──┴──┴─────────────────┴───┘
功能:设定下一个要存入数据的CGRAM的地址。


设定DDRAM地址指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┴──┴──┴──┴──┴──┴──┼───┤
ㄧ设定CGRAM   ㄧ 0  ㄧ 0  ㄧ 1  ㄧ          DDRAM的地址(7位)              ㄧ 40   ㄧ
ㄧ   地址     ㄧ    ㄧ    ㄧ    ㄧ                                        ㄧ      ㄧ
└──────┴──┴──┴──┴────────────────────┴───┘
功能:设定下一个要存入数据的DDRAM的地址。


读取忙信号或AC地址指令

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┼──┴──┴──┴──┴──┴──┴──┼───┤
ㄧ读取忙碌信号ㄧ 0  ㄧ 1  ㄧ FB ㄧ           AC内容(7位)                  ㄧ  40  ㄧ
ㄧ  或AC地址  ㄧ    ㄧ    ㄧ    ㄧ                                        ㄧ      ㄧ
└──────┴──┴──┴──┴────────────────────┴───┘
功能:<1> 读取忙碌信号BF的内容,BF=1表示液晶显示器忙,暂时无法接收单片机送来的数据或指令;
          当BF=0时,液晶显示器可以接收单片机送来的数据或指令;
      <2> 读取地址计数器(AC)的内容。


数据写入DDRAM或CGRAM指令一览

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┴──┴──┴──┴──┴──┴──┴──┼───┤
ㄧ 数据写入到 ㄧ    ㄧ    ㄧ                                              ㄧ      ㄧ
ㄧ DDRAM或    ㄧ 1  ㄧ 0  ㄧ            要写入的数据 D7~D0               ㄧ  40  ㄧ
ㄧ CGRAM      ㄧ    ㄧ    ㄧ                                              ㄧ      ㄧ
└──────┴──┴──┴───────────────────────┴───┘
功能:<1> 将字符码写入DDRAM,以使液晶显示屏显示出相对应的字符;
      <2> 将使用者自己设计的图形存入CGRAM。


从CGRAM或DDRAM读出数据的指令一览

┌──────┬─────────────────────────────┬───┐
ㄧ            ㄧ                      指令编码                            ㄧ 执行 ㄧ
ㄧ  指令功能  ├──┬──┬──┬──┬──┬──┬──┬──┬──┬──┤ 时间 ㄧ
ㄧ            ㄧ RS ㄧR/W ㄧDB7 ㄧDB6 ㄧDB5 ㄧDB4 ㄧDB3 ㄧDB2 ㄧDB1 ㄧDB0 ㄧ /us  ㄧ
├──────┼──┼──┼──┴──┴──┴──┴──┴──┴──┴──┼───┤
ㄧ  从CGRAM或 ㄧ    ㄧ    ㄧ                                              ㄧ      ㄧ
ㄧ  DDRAM读出 ㄧ 1  ㄧ 1  ㄧ            要读出的数据 D7~D0               ㄧ  40  ㄧ
ㄧ  数据      ㄧ    ㄧ    ㄧ                                              ㄧ      ㄧ
└──────┴──┴──┴───────────────────────┴───┘
功能:读取DDRAM或CGRAM中的内容。

细心的读者肯定发现了,在上面的指令集中,有RS、R/W和8位数据总线,却小了一个使能位E。使能位E对执行LCD指令起着关键作用,E有两个有效状态,高电平(1)和下降沿(1→0)。当E为高电平时,如果R/W为0,则LCD从单片机读入指令或者数据;如果R/W为1,则单片机可以从LCD中读出状态字(BF忙状态)和地址。而E的下降沿指示LCD执行其读入的指令或者显示其读入的数据。下面是HD44780的时序图和时间参数表:



在此不准备细究其时序图,对初学者来说,只要记住,在将E置高电平前,先设置好RS和R/W信号,在E下降沿到来之前,准备好写入的命令字或数据。只需在适当的地方加上延时,就可以满足要求了

基本操作时序:

读状态  输入:RS=L,RW=H,E=H                             输出:DB0~DB7=状态字
写指令  输入:RS=L,RW=L,E=下降沿脉冲,DB0~DB7=指令码   输出:无
读数据  输入:RS=H,RW=H,E=H                             输出:DB0~DB7=数据
写数据  输入:RS=H,RW=L,E=下降沿脉冲,DB0~DB7=数据     输出:无

系统分类: 显示光电  |  用户分类: 非技术人生  |  标签: 无标签  |  来源: 转贴  | 

点击查看原文

发表评论 阅读全文(618) | 回复(0)

发表于 2008/10/16 11:42:57

0

关于投票

【046】基于HD44780的1602简单驱动(C51)

【046】基于HD44780的1602简单驱动(C51)

点击数:1963    发布日期:2007-5-26 1:36:00  
【收藏】 【评论】 【打印】 【编程爱好者论坛】 【关闭】

 


[相关] (001)基于HD44780液晶芯片的16×2字符型液晶(1602)简介。


lcd.h:

  • /*********************************************************************  
  • * 标题: 基于HD44780的1602简单驱动(C51)  
  • * 文件: lcd.h  
  • * 作者: wentao     http://blog.liuwentao.net  
  •                    http://wentao.programfan.com  
  • * 参考: AVR单片机与CPLD/FPGA综合应用入门  
  • * 日期: 2007.5.10  
  • * 修改: 2007.5.26  
  • * 软件: Keil C51 V8.02  
  • * 芯片: AT89X51  
  • * 说明: 硬件连接定义及函数原型声明,此处P0,P2,P2_0等在AT89X51.h中定义,  
  •         也可用sfr, sbit自行定义。  
  • * 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!   
  • *********************************************************************/  
  •   
  • #ifndef LCD_H   
  • #define LCD_H   
  •   
  • #include <AT89X51.h>   
  •   
  • #define LCD_DATA_PORT P0  // 液晶BD0~BD7与P0口相连   
  •   
  • #define LCD_RS P2_0       // 液晶 RS  引脚与P2.0相接   
  • #define LCD_RW P2_1       // 液晶 R/W 引脚与P2.1相接   
  • #define LCD_E  P2_2       // 液晶 E   引脚与P2.2相接   
  • #define LCD_BF P0_7       // 液晶 DB7 引脚与P0.7相接 Busy Flag   
  •   
  • // 函数原型   
  •   
  • // 向LCD写命令字   
  • extern void lcd_command(unsigned char cmd);   
  •   
  • // 设置显示位置(即写入显示地址),行列均从0开始   
  • extern void lcd_goto_xy(unsigned char x, unsigned char y);   
  •   
  • // 写字符(传入的参数实际为所需显示字符的地址,即液晶字符产生器中字符的地址)   
  • extern void lcd_putc(unsigned char c);   
  •   
  • // 指定位置写字符   
  • extern void lcd_xy_putc(unsigned char x, unsigned char y, unsigned char c);   
  •   
  • // 写字符串   
  • extern void lcd_puts(unsigned char *s);   
  •   
  • // 指定位置写字符串   
  • extern void lcd_xy_puts(unsigned char x, unsigned char y, unsigned char *s);   
  •   
  • // LCD初始化   
  • extern void lcd_init(void);   
  •   
  • #endif //LCD_H  



    lcd.c:
  • /*********************************************************************  
  • * 标题: 基于HD44780的1602简单驱动(C51)  
  • * 文件: lcd.c  
  • * 作者: wentao     http://blog.liuwentao.net  
  •                    http://wentao.programfan.com  
  • * 参考: AVR单片机与CPLD/FPGA综合应用入门  
  • * 日期: 2007.5.10  
  • * 修改: 2007.5.26  
  • * 软件: Keil C51 V8.02  
  • * 芯片: AT89X51  
  • * 说明: 硬件连接定义在lcd.h中  
  • * 声明: 自用存档!另仅供需要的朋友参考,请勿用做不道德转载及商业用途!   
  • *********************************************************************/  
  •   
  • #include "lcd.h"   
  •   
  • // 本地函数   
  •   
  • void lcd_delay_us(unsigned char us) // 延时微秒@12M,ms最大值255   
  • {   
  •     while(--us)   
  •     {   
  •         ;   
  •     }   
  • }   
  •   
  • void lcd_delay_ms(unsigned char ms) // 延时毫秒@12M,ms最大值255   
  • {      
  •     unsigned char i;   
  •     while(ms--)   
  •     {   
  •         for(i = 0; i < 124; i++)   
  •         {   
  •             ;   
  •         }   
  •     }   
  • }   
  •   
  •   
  • // 产生一个使能脉冲   
  •   
  • void lcd_e_toggle(void)   
  • {   
  •     LCD_E = 1;   
  •     lcd_delay_us(3);   
  •     LCD_E = 0;   
  • }   
  •   
  •   
  • // 循环检测LCD忙标志(BF),直到其值为0,方可执行下一指令   
  •   
  • void lcd_wait_until_finish(void)   
  • {   
  •     LCD_RW = 1;              // RW置1,状态为读   
  •     LCD_RS = 0;              // RS置0,读状态时RS需置低电平       
  •     LCD_E = 1;               // E 置1,读取信息   
  •        
  •     while(LCD_BF)            // 循环直至BF=0   
  •     {   
  •         ;   
  •     }   
  •     LCD_E = 0;               // E重置为0   
  • }   
  •   
  •   
  • // 公共函数   
  •   
  • // 向LCD写命令字   
  •   
  • void lcd_command(unsigned char cmd)   
  • {   
  •     LCD_RW = 0;              // RW置0,状态为写   
  •     LCD_RS = 0;              // RS置0,写入命令字   
  •        
  •     LCD_DATA_PORT = cmd;     // 将命令字cmd送入LCD的数据端口   
  •     lcd_e_toggle();          // 产生使能脉冲,在下降沿开始执行,将命令字读入   
  •     lcd_wait_until_finish(); // 等待执行完毕   
  • }   
  •   
  •   
  • // 设置显示位置(即写入显示地址),x,y均从0开始   
  •   
  • void lcd_goto_xy(unsigned char x, unsigned char y)   
  • {   
  •     unsigned char p;       // p为字符显示位置,即DDRAM中的地址   
  •     if (y==0)   
  •     {   
  •         p = 0x00 + x;      // (0,0)显示位置为0x00   
  •     }   
  •     else  
  •     {   
  •         p = 0x40 + x;      // (0,1)显示位置为0x40   
  •     }   
  •     lcd_command(p + 0x80); // 写入显示地址时DB7须为高电平,加0x80   
  • }   
  •   
  •   
  • // 写字符(传入的参数实际为所需显示字符的地址,即液晶字符产生器中字符的地址)   
  •   
  • void lcd_putc(unsigned char c)   
  • {   
  •     LCD_RW = 0;               // RW置0,状态为写   
  •     LCD_RS = 1;               // RS置1,写入数据   
  •        
  •     LCD_DATA_PORT = c;        // 将字符c(实际上是字符的地址)送入LCD数据端口   
  •     lcd_e_toggle();           // 使能脉冲   
  •     lcd_wait_until_finish();  // 等待完成   
  • }   
  •   
  •   
  • // 指定位置写字符   
  •   
  • void lcd_xy_putc(unsigned char x, unsigned char y, unsigned char c)   
  • {   
  •     lcd_goto_xy(x,y);   
  •     lcd_putc(c);   
  • }   
  •   
  •   
  • // 写字符串   
  •   
  • void lcd_puts(unsigned char *s)   
  • {   
  •     while(*s)   
  •     {   
  •         lcd_putc(*s);   
  •         s++;   
  •     }   
  • }   
  •   
  •   
  • // 指定位置写字符串   
  •   
  • void lcd_xy_puts(unsigned char x, unsigned char y, unsigned char *s)   
  • {   
  •     lcd_goto_xy(x, y);   
  •     lcd_puts(s);   
  • }   
  •   
  • // LCD初始化   
  •   
  • void lcd_init(void)   
  • {   
  •     lcd_delay_ms(12);          // 上电后适当延时   
  •     lcd_command(0x38);         // 设为8位接口模式,显示2行字符   
  •     lcd_command(0x06);         // 写入新数据后光标右移   
  •     lcd_command(0x0c);         // 显示功能开,不显示光标   
  •     lcd_command(0x01);         // 清屏   
  • }




    测试:

  • #include "lcd.h"   
  •   
  • void main(void)   
  • {   
  •     while(1)   
  •     {   
  •         lcd_init();                // 初始化LCD   
  •            
  •         lcd_goto_xy(0,0);          // 字符位置:(0,0)   
  •         lcd_putc('a');             // 显示字符"a"   
  •   
  •         lcd_putc(0x62);            // 在(1,0)显示字符"b"(在CGROM中的地址为0x62,与ASCII码对应)   
  •   
  •         lcd_xy_putc(3,0,'c');      // 在(3,0)显示字符"c"   
  •   
  •         lcd_goto_xy(0,1);          // 字符位置:(0,1)   
  •         lcd_puts("Hello world!");  // 显示字符串"Hello world!"   
  •                
  •         lcd_xy_puts(16-3,1,"^_^"); // 在(13,1)列显示字符串"^_^"   
  •     }   
  • }
  • 系统分类: 显示光电  |  用户分类: 非技术人生  |  标签: 无标签  |  来源: 转贴  | 

    点击查看原文

    发表评论 阅读全文(530) | 回复(0)

    Total , Page /