zoukankan      html  css  js  c++  java
  • 简析LCD1602液晶驱动及在Arduino上的实例实现

    这几日在倒腾新到的Arduino,比起普通单片机来,感觉写程序太简单了。不过和外设打交道还是没那么容易,比如今天要说的看似简单的LCD1602液晶,却费了我一整天才基本搞懂,不过还是有一个小问题没有实现/解决。好在不怎么用那个功能,就没有再去深究。

    其实之前做课设时接触过LCD1602,不过那时用的是51,而且是八位数据线接法,当时就挺苦恼1602的连线的,16根连线在板子上飞,那叫壮观。所以,今天我特地实现并搞懂了LCD1602的四位数据线接法,并完成了驱动程序,除了那个读数据的功能没有实现。

    假定大家对LCD1602已经有了一定认识,我们就先来看下LCD1602的指令:

     

    序号

    指令

    RS

    R/W

    D7

    D6

    D5

    D4

    D3

    D2

    D1

    D0

    1

    清显示

    0

    0

    0

    0

    0

    0

    0

    0

    0

    1

    2

    光标返回

    0

    0

    0

    0

    0

    0

    0

    0

    1

    *

    3

    输入模式设置

    0

    0

    0

    0

    0

    0

    0

    1

    I/D

    S

    4

    显示开关控制

    0

    0

    0

    0

    0

    0

    1

    D

    C

    B

    5

    光标或者字符移位

    0

    0

    0

    0

    0

    1

    S/C

    R/L

    *

    *

    6

    功能设置

    0

    0

    0

    0

    1

    DL

    N

    F

    *

    *

    7

    字符发生储存器地址设置

    0

    0

    0

    1

    字符发生储存器地址

    8

    数据储存器地址设置

    0

    0

    1

    显示数据储存器地址

    9

    读忙标志和地址

    0

    1

    BF

    计数器地址

    10

    写数到CGRAM(or DDRAM)

    1

    0

    要写的数据内容

    11

    从CGRAM或DDRAM读数据

    1

    1

    读出的数据内容

    关于对上表格的具体代码说明:1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1为高电平、0为低电平)

    指令1:清显示,指令码01H,光标复位到地址00H位置。

    指令2:光标复位,光标返回到地址00H。

    指令3:光标和显示模式设置
     I/D:光标移动方向,高电平右移,低电平左移
     S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。

    指令4:显示开关控制。
     D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示
     C:控制光标的开与关,高电平表示有光标,低电平表示无光标
     B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。

    指令5:光标或显示移位
     S/C:高电平时移动显示的文字,低电平时移动光标。

    指令6:功能设置命令
     DL:高电平时为4位总线,低电平时为8位总线
     N:低电平时为单行显示,高电平时双行显示
     F: 低电平时显示5×7的点阵字符,高电平时显示5×10的点阵字符。

    指令7:字符发生器RAM地址设置。

    指令8:DDRAM地址设置。

    指令9:读忙信号和光标地址
     BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。

    指令10:写数据。

    指令11:读数据。

    可能大家看了上表有些困惑,怎么用呢?其实就是几条不重叠的指令,如果你想要设置成你自己的风格,对应上表指令填充好指定的位后换算成2位16进制,0xFF的形势。然后在初始化函数中或者显示之前对1602输出该指令,即可达到效果。但是上面那么多设置,有好多指令,怎么分先后呢?这点我不是很清楚,也没有去尝试,一般的手册给出了1602初始化指令的顺序,如下:

    1.  延时15 ms
    2.  写指令38H(不检测忙信号)
    3.  延时5 ms
    4.  写指令38H(不检测忙信号)
    5.  延时5 ms
    6.  写指令38H(不检测忙信号)
    7. 以后每次写指令、读/写数据操作均需要检测忙信号
    8.  写指令38H:显示模式设置
    9.  写指令08H:显示关闭
    10.  写指令01H:显示清屏
    11.  写指令06H:显示光标移动设置
    12.  写指令0CH:显示开及光标设置

    至此,初始化完成。

    注意:以上1~6条照写,8~12条则根据自己情况写。比如,我要用四位数据总线连接LCD1602显示,则第8条指令相应改为28H。如果要显示并闪烁光标,12条相应改为0FH。并且,如果想要在使用中对LCD1602设置进行修改,可随时对其赋相应指令。

    同时给出LCD1602时序图,供大家参考。

    读状态    输入:RS=L,R/W=H,E=H                                  输出:D0—D7=状态字
    写指令    输入:RS=L,R/W=L,D0—D7=指令码,E=高脉冲       输出:无
    读数据    输入:RS=H,R/W=H,E=H                                  输出:D0—D7=数据
    写数据    输入:RS=H,R/W=L,D0—D7=数据,E=高脉冲          输出:无

    下面给出LCD1602的四位数据线接法的驱动函数。

     

       1:  /***************************************************************
       2:  * LCD1602 四位数据线连接驱动+实例 For Arduino 
       3:  * 
       4:  *主要实现了在Arduino下四位数据线连接LCD1602液晶显示,未实现数据读取。
       5:      (这方面的资料网上似乎很少,反正我是没找到。手册也是五花八门,
       6:      未见其介绍如何在四位数据线连接下获取LCD1602的数据。) 
       7:      代码中除函数Init_LCD1602中延迟时间较标准外,其它未予深究,
       8:      请不要以此拍砖。另外,写指令和写数据函数 
       9:      中的方法引自他处,虽有些晦涩,不过理解后感觉挺精妙的,就没有改。 
      10:      若要更换显示风格设置,请自行修改初始化函数中的内容。 
      11:  *作者:Wave 
      12:  *联系方式:sxwangbo@live.com 
      13:  *日期:2013年8月9日 
      14:  ***************************************************************/
      15:   
      16:  /*如果要更改此三处引脚,请在初始化函数Init_LCD1602()
      17:  *或setup()中手动指定所用引脚为输出模式。这里的排序可能有点坑爹。
      18:  *开始是为了对应Arduino的LCD1602库的脚排序,方便调试。后来就没有改。*/
      19:  int LCD1602_RS=12; 
      20:  int LCD1602_RW=10;
      21:  int LCD1602_EN=11;
      22:  //要求四脚连续并从小到大排序,依次对应LCD1602的D7、D6、D5、D4脚。
      23:  int DB[] = {2,3,4,5};
      24:  char str1[]="Welcome to"; 
      25:  char str2[]="Matrix.Studio"; 
      26:  char str3[]="It's My Arduino."; 
      27:  char str4[]="Do U think of it?"; 
      28:  char str5[]="Arduino is a single-board microcontroller to "+
      29:      "make using electronics in multidisciplinary projects "+
      30:      "more accessible. The hardware consists of a simple open "+
      31:      "source hardware board designed around an 8-bit Atmel AVR "+
      32:      "microcontroller, or a 32-bit Atmel ARM. The software "+
      33:      "consists of a standard programming language compiler "+
      34:      "and a boot loader that executes on the microcontroller. ";
      35:   
      36:   
      37:  //判断LCD1602是否忙,遇忙等待 
      38:  void Check_LCD1602_Busy() 
      39:  { 
      40:      digitalWrite(LCD1602_RS,LOW); 
      41:      digitalWrite(LCD1602_RW,HIGH); 
      42:      digitalWrite(LCD1602_EN,HIGH); 
      43:      pinMode(DB[0],INPUT); 
      44:      while(digitalRead(DB[0])==HIGH); 
      45:      pinMode(DB[0],OUTPUT); 
      46:      digitalWrite(LCD1602_EN,LOW); 
      47:      return; 
      48:  }
      49:   
      50:  //给LCD1602写指令 
      51:  void Write_LCD1602_Command(int data) 
      52:  { 
      53:      Check_LCD1602_Busy(); 
      54:      Write_LCD1602_Init_Command(data); 
      55:  }
      56:   
      57:  //给LCD1602写指令,未检测忙状态,仅供初始化用 
      58:  void Write_LCD1602_Init_Command(int command) 
      59:  { 
      60:      int i,temp; 
      61:      digitalWrite( LCD1602_RS,LOW); 
      62:      digitalWrite( LCD1602_RW,LOW); 
      63:      digitalWrite( LCD1602_EN,LOW); 
      64:      
      65:      temp=command & 0xf0; 
      66:      for (i=DB[0]; i < DB[0]+4; i++) 
      67:      { 
      68:         digitalWrite(i,temp & 0x80); 
      69:         temp <<= 1; 
      70:      } 
      71:      
      72:      digitalWrite( LCD1602_EN,HIGH); 
      73:      delayMicroseconds(1); 
      74:      digitalWrite( LCD1602_EN,LOW); 
      75:      
      76:      temp=(command & 0x0f)<<4; 
      77:      for (i=DB[0]; i < DB[0]+5; i++) 
      78:      { 
      79:         digitalWrite(i,temp & 0x80); 
      80:         temp <<= 1; 
      81:      } 
      82:      
      83:      digitalWrite( LCD1602_EN,HIGH); 
      84:      delayMicroseconds(1); 
      85:      digitalWrite( LCD1602_EN,LOW); 
      86:  }
      87:   
      88:  //写数据到LCD1602上。 
      89:  void Write_LCD1602_Data(int data) 
      90:  { 
      91:      Check_LCD1602_Busy(); 
      92:      int i=0,temp; 
      93:      digitalWrite( LCD1602_RS,HIGH); 
      94:      digitalWrite( LCD1602_RW,LOW); 
      95:      digitalWrite( LCD1602_EN,LOW); 
      96:      
      97:      temp=data & 0xf0; 
      98:      for (i=DB[0]; i < DB[0]+4; i++) 
      99:      { 
     100:         digitalWrite(i,temp & 0x80); 
     101:         temp <<= 1; 
     102:      } 
     103:      
     104:      digitalWrite( LCD1602_EN,HIGH); 
     105:      delayMicroseconds(1); 
     106:      digitalWrite( LCD1602_EN,LOW); 
     107:      
     108:      temp=(data & 0x0f)<<4; 
     109:      for (i=DB[0]; i < DB[0]+5; i++) 
     110:      { 
     111:         digitalWrite(i,temp & 0x80); 
     112:         temp <<= 1; 
     113:      } 
     114:      
     115:      digitalWrite( LCD1602_EN,HIGH); 
     116:      delayMicroseconds(1); 
     117:      digitalWrite( LCD1602_EN,LOW); 
     118:  }
     119:   
     120:  //清除指定屏幕区域内容,即以空格填充 
     121:  void Clear_LCD1602_Display(int x, int y, int length) 
     122:  { 
     123:      int i=0; 
     124:      Write_LCD1602_Command(0x80 + 0x40*x + y); 
     125:      for(i=y;i<length;i++) 
     126:          Write_LCD1602_Data(0x20);//0x20为空格对应ASCII码 
     127:  }
     128:   
     129:  //将指定字符输出到LCD1602上。
     130:  //其中x为行(0~1),y为列(0~15),data为指定字符 
     131:  void Write_LCD1602_Char(int x, int y, int data) 
     132:  { 
     133:      Write_LCD1602_Command(0x80 + 0x40*x + y); 
     134:      Write_LCD1602_Data(data); 
     135:  }
     136:   
     137:  //将指定字符串输出到LCD1602上。
     138:  //其中x为行(0~1),y为列(0~15),*s为指定字符串指针 
     139:  void Write_LCD1602_String(int x,int y,char *s) 
     140:  { 
     141:      Write_LCD1602_Command(0x80 + 0x40*x + y); 
     142:      while (*s)             //写字符串 
     143:      { 
     144:          Write_LCD1602_Data(*s);   
     145:          s ++; 
     146:      } 
     147:  }
     148:   
     149:  //将指定文段输出显示到LCD1602上。
     150:  //其中x为行(0~1),y为列(0~15),*s为指定字符串指针 
     151:  void Write_LCD1602_Paragraph(int x, int y, char *s) 
     152:  { 
     153:      Write_LCD1602_Command(0x0F); 
     154:      Write_LCD1602_Command(0x80 + 0x40*x + y); 
     155:      while (*s)             //写字符串 
     156:      {        
     157:          Write_LCD1602_Data(*s); 
     158:          s ++; 
     159:          if(*s==' ') 
     160:              delay(500); 
     161:          if(y++==15) 
     162:          { 
     163:              Write_LCD1602_Command(0xC0); 
     164:          } 
     165:          if(y==32) 
     166:          { 
     167:              delay(1000); 
     168:              Write_LCD1602_Command(0x01); 
     169:              Write_LCD1602_Command(0x80);            
     170:              y=0;            
     171:          } 
     172:          delay(100); 
     173:      } 
     174:      Write_LCD1602_Command(0x0E); 
     175:      delay(3000); 
     176:  }
     177:   
     178:  //较标准的LCD1602初始化函数 
     179:  void Init_LCD1602() 
     180:  { 
     181:      int i = 0; 
     182:      for (i=DB[0]; i < DB[0]+4; i++) 
     183:      { 
     184:          pinMode(i,OUTPUT); 
     185:      } 
     186:      for (i=10; i < 13; i++) 
     187:      { 
     188:          pinMode(i,OUTPUT); 
     189:      } 
     190:      
     191:      delay(15); 
     192:      Write_LCD1602_Init_Command(0x38); 
     193:      delay(5); 
     194:      Write_LCD1602_Init_Command(0x38); 
     195:      delay(5); 
     196:      Write_LCD1602_Init_Command(0x38); 
     197:      
     198:      Write_LCD1602_Command(0x28);        //4位数据线 
     199:      Write_LCD1602_Command(0x08);        //关闭显示 
     200:      Write_LCD1602_Command(0x01);        //清除屏幕内容 
     201:      Write_LCD1602_Command(0x06);        //光标右移,文字不移 
     202:      Write_LCD1602_Command(0x0F);        //打开显示,显示光标且闪烁 
     203:  }
     204:   
     205:  void setup (void) 
     206:  { 
     207:      Init_LCD1602(); 
     208:      delay(50); 
     209:  }
     210:   
     211:  void loop (void) 
     212:  { 
     213:      //清屏 
     214:      Write_LCD1602_Command(0x01); 
     215:      Write_LCD1602_String(0,0,str1);//第1行,第4个地址起 
     216:      delay(50); 
     217:      Write_LCD1602_String(1,0,str2);//第2行,第2个地址起 
     218:      delay(2000);    
     219:      Write_LCD1602_Command(0x01); 
     220:      delay(50); 
     221:      Write_LCD1602_String(0,0,str3); 
     222:      delay(50); 
     223:      Write_LCD1602_String(1,0,str4); 
     224:      delay(2000); 
     225:      Write_LCD1602_Command(0x01); 
     226:      delay(50); 
     227:      Write_LCD1602_Paragraph(0,0,str5); 
     228:  } 
  • 相关阅读:
    317 随笔
    316 随笔
    315 随笔
    python 第一章
    matlab 第四章 第一节 字符串 元胞
    matlab 第三章 第二节 多维数组
    matlab 第三章
    python 循环+break continue
    Springboot 教程 导入
    matlab 第二章 第三节 数值表示、变量及表达式
  • 原文地址:https://www.cnblogs.com/sanwave/p/3248340.html
Copyright © 2011-2022 走看看