簡析LCD1602液晶驅動及在Arduino上的實例實現

這幾日在倒騰新到的Arduino,比起普通單片機來,感受寫程序太簡單了。不過和外設打交道仍是沒那麼容易,好比今天要說的看似簡單的LCD1602液晶,卻費了我一成天才基本搞懂,不過仍是有一個小問題沒有實現/解決。好在不怎麼用那個功能,就沒有再去深究。css

其實以前作課設時接觸過LCD1602,不過那時用的是51,並且是八位數據線接法,當時就挺苦惱1602的連線的,16根連線在板子上飛,那叫壯觀。因此,今天我特意實現並搞懂了LCD1602的四位數據線接法,並完成了驅動程序,除了那個讀數據的功能沒有實現。html

假定你們對LCD1602已經有了必定認識,咱們就先來看下LCD1602的指令:git

 

序號編程

指令electron

RS函數

R/Woop

D7ui

D6spa

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的D七、D六、D五、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:  } 
相關文章
相關標籤/搜索