Arduino下LCD1602綜合探究(上)——1602的兩種驅動方式,如何使LCD的控制編程變得更簡單


本文為大大維原創,最早於博客園發表,轉載請注明出處!!!

 

一、前言:

  LCD ( Liquid Crystal Display 的簡稱)液晶顯示器,已經逐漸替代CRT成為主流的顯示設備之一,因此也成為了單片機發燒友繞不過的話題之一;而LCD1602更是很多單片機發燒友最早接觸的字符型液晶顯示器。筆者經過一段時間的深入學習,對其驅動有了些許心得,特地記錄於此,以備以后查閱。

  LCD1602,也叫1602液晶,是一種專門用來顯示字母、數字、符號等的點陣型液晶模塊,工業字符型液晶的一種,能夠同時顯示16x02即32個字符。主控芯片是HD44780或者其它兼容芯片,而市面上字符液晶大多數是基於HD44780液晶芯片的,控制原理是完全相同的。因此盡管LCD1602可顯示的內容十分有限,但在此花點時間是完全值得的。

二、LCD的一些背景知識:

<1>LCD1602基本參數及引腳功能:

1.LCD1602的分類:

  LCD1602分為帶背光和不帶背光兩種,帶背光的比不帶背光的厚,是否帶背光在應用中並無差別,兩者尺寸差別如下圖10-54所示:

在本文中,筆者選用的是帶背光的一種。

  

2.基本參數:

顯示容量:16×2個字符

芯片工作電壓:4.5—5.5V

工作電流:2.0mA(5.0V)

模塊最佳工作電壓:5.0V

字符尺寸:2.95×4.35(W×H)mm

2.引腳功能說明

  1602LCD采用標准的14腳(無背光)或16腳(帶背光)接口,各引腳接口說明如下:

編號

符號

引腳說明

編號

符號

引腳說明

1

VSS

電源地

9

D2

數據

2

VDD

電源正極

10

D3

數據

3

VL

液晶顯示偏壓

11

D4

數據

4

RS

數據/命令選擇

12

D5

數據

5

R/W

讀/寫選擇

13

D6

數據

6

E

使能信號

14

D7

數據

7

D0

數據

15

BLA

背光源正極

8

D1

數據

16

BLK

背光源負極

 

各引腳說明:

第1腳:VSS為地電源。

第2腳:VDD接5V正電源。

第3腳:VL為液晶顯示器對比度調整端,接正電源時對比度最弱,接地時對比度最高,對比度過高時會產生“鬼影”,使用時可以通過一個10K的電位器調整對比度。

第4腳:RS為寄存器選擇,高電平時選擇數據寄存器、低電平時選擇指令寄存器。

第5腳:R/W為讀寫信號線,高電平時進行讀操作,低電平時進行寫操作。當RS和R/W共同為低電平時可以寫入指令或者顯示地址,當RS為低電平R/W為高電平時可以讀忙信號,當RS為高電平R/W為低電平時可以寫入數據。

第6腳:E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。

第7~14腳:D0~D7為8位雙向數據線。

第15腳:背光源正極。

第16腳:背光源負極

<2>LCD1602的指令說明及時序

1.與HD44780相兼容的芯片時序表如下:

讀狀態

輸入

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=高脈沖

輸出

 

2.LCD1602的指令說明:

  1602液晶模塊內部的控制器共有11條控制指令,如表所示:

序號

指令

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或DDRAM

1

0

要寫的數據內容

11

從CGRAM或DDRAM讀數

1

1

讀出的數據內容

 

者在百度文庫中發現一個特別好的介紹1602指令集的文章,給大家分享如下:

點擊查看

<3>LCD1602的RAM地址映射及標准字庫表

1.LCD1602的RAM地址映射

 

  液晶顯示模塊是一個慢顯示器件,所以在執行每條指令之前一定要確認模塊的忙標志為低電平,表示不忙,否則此指令失效。要顯示字符時要先輸入顯示字符地址,也就是告訴模塊在哪里顯示字符,下圖是1602的內部顯示地址:

 

在對液晶模塊的初始化中要先設置其顯示模式,在液晶模塊顯示字符時光標是自動右移的,無需人工干預。每次輸入指令前都要判斷液晶模塊是否處於忙的狀態。

2.LCD1602的標准字庫表

  1602液晶模塊內部的字符發生存儲器(CGROM)已經存儲了160個不同的點陣字符圖形,如下圖所示,這些字符有:阿拉伯數字、英文字母的大小寫、常用的符號、和日文假名等。

 

在使用標准字庫中的字符圖形時,無需自己制作字模即可直接使用,若要顯示漢字等標准字庫中沒有的元素,則需要自己在DDRAM中制作字模。

<4>LCD1602四線驅動的約定流程

1、  寫入指令:

1) EN = 0 (LCD使能禁止)

2) 短延時

3) RS = 0  ,RW = 0  (准備寫入指令)

4) DATA = 指令的高4位(ATA代表D7、D6、D5、D4,下同)

5) 短延時

6) EN = 1 (LCD使能允許,指令寫入)

7) 短延時

8) EN = 0 (LCD使能禁止)

9) DATA = 指令的低4位 

10) 短延時

11) EN = 1 (LCD使能允許,指令寫入)

12) 短延時

13) EN = 0 (LCD使能禁止)

14) 短延時

2、  寫入數據:

1) EN = 0 (LCD使能禁止)

2) 短延時

3) RS = 1 ,RW = 0 (准備寫入數據)

4) DATA = 數據的高4位

5) 短延時

6) EN = 1 (LCD使能允許,數據寫入)

7) 短延時

8) EN = 0 (LCD使能禁止)

9) DATA = 數據的低4位

10) 短延時

11) EN = 1 (LCD使能允許,數據寫入)

12) 短延時

13) EN = 0 (LCD使能禁止)

14) 短延時

三、關於LCD控制庫LiquidCrystal:

  LiquidCrystal是Arduino的官方庫之一,他可以控制基於日立公司HD44780(或兼容)芯片集成的字符型LCD。該庫可以通過四線或者八線模式控制LCD。

無疑,LiquidCrystal庫可以使LCD的控制編程變得十分簡單!!!

筆者在學習中,發現了一個比較完整的LiquidCrystal庫的中文資料,鏈接如下:

點擊查看

下面,就一些常用的LiquidCrystal庫函數做一個簡單介紹:

1.LiquidCrystal()構造函數

2.begin()指定顯示方式

3.clear()清屏,光標置於左上角

4.home()接下來的字符從左上角顯示

5.setCursor(col,row)設置光標位置

6.print()LCD顯示字符

四、Arduino下的LCD1602的8線驅動模式:

<1>優缺點

 八線模式的優點是每位數據均從單獨的數據線傳輸,因此數據傳輸速度快。但缺點也是顯然的,需要占掉大量的端口。

<2>接線方式

VL為液晶顯示器對比度調整端,有條件的話,最好使用一個10K的電位器來調整對比度。限於條件,筆者通過反復調試,最后選擇了4k電阻,效果也還可以。

<3>試驗代碼

1.不使用LiquidCrystal庫

  1 /*Arduino在8位接法下不使用LiquidCrystal庫
  2 * 輸出歡迎界面和Hello World!
  3 * 作者:大大維
  4 * 2016/10/23
  5 */
  6 
  7 int RS = 12;                             //數據/命令選擇器引腳(RS)    
  8 int RW = 11;                            //讀/寫選擇器引腳(R/W)
  9 int DB[] = {3, 4, 5, 6, 7, 8, 9, 10};    //使用數組來定義總線需要的管腳(D0-D7)
 10 int Enable = 2;                            //使能(E)    
 11 
 12 void LcdCommandWrite(int value) {
 13     // 定義所有引腳
 14     int i = 0;
 15     digitalWrite(RS, LOW);
 16     digitalWrite(RW, LOW);
 17     for (i=DB[0]; i <= RS; i++) //總線賦值
 18     {
 19         //這里的&是二進制的“與”運算。取指令碼的最低位。
 20        digitalWrite(i,value & 0x01);
 21        value >>= 1;
 22     }
 23     digitalWrite(Enable,LOW);
 24     delayMicroseconds(1);        // 延時1us
 25     digitalWrite(Enable,HIGH);
 26     delayMicroseconds(1);          // 延時1us
 27     digitalWrite(Enable,LOW);
 28     delayMicroseconds(1);          // 延時1us
 29 }
 30 
 31 void LcdDataWrite(int value) {
 32     // 定義所有引腳
 33     int i = 0;
 34     digitalWrite(RS, HIGH);
 35     digitalWrite(RW, LOW);
 36     for (i=DB[0]; i <= DB[7]; i++) {
 37        digitalWrite(i,value & 0x01);
 38        value >>= 1;
 39     }
 40     digitalWrite(Enable,LOW);
 41     delayMicroseconds(1);        // 延時1us
 42     digitalWrite(Enable,HIGH);
 43     delayMicroseconds(1);        // 延時1us
 44     digitalWrite(Enable,LOW);
 45     delayMicroseconds(1);          // 延時1us
 46 }
 47 
 48 void setup (void) {
 49     int i = 0;
 50     for (i=Enable; i <= RS; i++) {
 51        pinMode(i,OUTPUT);   
 52     }
 53     delay(100);
 54     // 短暫的停頓后初始化LCD
 55     // 用於LCD控制需要
 56     LcdCommandWrite(0x38);         // 設置為8-bit接口,2行顯示,5x7文字大小                     
 57     delay(20);                      
 58     LcdCommandWrite(0x06);        // 輸入方式設定,自動增量,畫面沒有移位
 59     delay(20);                      
 60     LcdCommandWrite(0x0C);        // 顯示設置,開啟顯示屏,光標關,無閃爍
 61     delay(20);                                  
 62 }
 63 
 64 void loop (void) {
 65   LcdCommandWrite(0x01);           // 屏幕清空,光標位置歸零  
 66   delay(10); 
 67   LcdCommandWrite(0x80+5);         // 定義光標位置為第一行第五個位置
 68   delay(10);                     
 69   // 寫入歡迎信息 
 70   LcdDataWrite('W');
 71   LcdDataWrite('e');
 72   LcdDataWrite('l');
 73   LcdDataWrite('c');
 74   LcdDataWrite('o');
 75   LcdDataWrite('m');
 76   LcdDataWrite('e');
 77   delay(10);
 78   LcdCommandWrite(0xc0+2);          // 定義光標位置為第二行第二個位置  
 79   delay(10); 
 80   LcdDataWrite('I');
 81   LcdDataWrite(' ');
 82   LcdDataWrite('a');
 83   LcdDataWrite('m');
 84   LcdDataWrite(' ');
 85   LcdDataWrite('D');
 86   LcdDataWrite('a');
 87   LcdDataWrite('D');
 88   LcdDataWrite('a');
 89   LcdDataWrite('W');
 90   LcdDataWrite('e');
 91   LcdDataWrite('i');
 92   delay(3000);
 93   LcdCommandWrite(0x01);            // 屏幕清空,光標位置歸零
 94   delay(10);
 95   LcdCommandWrite(0x80+2);          //定義光標位置為第一行第二個位置
 96   delay(10);  
 97   LcdDataWrite('H');
 98   LcdDataWrite('e');
 99   LcdDataWrite('l');
100   LcdDataWrite('l');
101   LcdDataWrite('o');
102   LcdDataWrite(' ');
103   LcdDataWrite('W');
104   LcdDataWrite('o');
105   LcdDataWrite('r');
106   LcdDataWrite('l');
107   LcdDataWrite('d');
108   LcdDataWrite('!');
109   delay(5000);
110 }

 

 看到上面的代碼,是否覺得略顯復雜?但要是使用了LiquidCrystal庫,一切將變得十分簡單!!!

2.使用LiquidCrystal庫

 1 /*Arduino在8位接法下使用LiquidCrystal庫
 2 * 輸出歡迎界面和Hello World!
 3 * 作者:大大維
 4 * 2016/10/23
 5 */
 6 #include<LiquidCrystal.h>
 7 LiquidCrystal lcd(12,11,3,4,5,6,7,8,9,10);           //初始化LCD
 8 void setup(){
 9     lcd.begin(16,2);                                 //設置LCD為16列*2行
10 }
11 void loop(){
12     lcd.clear();                                    //清屏操作
13     lcd.setCursor(5,0);                              //設置光標位置為第一行,第六列
14     lcd.print("Welcome");                           //在LCD上輸出信息
15     delay(10);                                       //延時程序
16     lcd.setCursor(2,1);
17     lcd.print("I am DaDaWei");
18     delay(3000);
19     lcd.clear();
20     lcd.setCursor(2,0);
21     lcd.print("Hello World!");
22     delay(5000);
23 }

<4>試驗展示

演示視頻

五、Arduino下的LCD1602的四線驅動模式:

<1>優缺點

 四線模式相對於八線模式的優點是占用的端口更少,減少了四條數據線,也就是說八位的數據需要通過四條線來發送,那么會導致四線模式比八線模式數據速度慢些。

<2>接線方式

<3>試驗代碼

 1.不使用LiquidCrystal庫

  1 /*Arduino在4位接法下不使用LiquidCrystal庫
  2 * 輸出歡迎界面和Hello World!
  3 * 作者:大大維
  4 * 2016/10/23
  5 */
  6 
  7 int RS = 12;                             //數據/命令選擇器引腳(RS)    
  8 int RW = 11;                            //讀/寫選擇器引腳(R/W)
  9 int DB[] = {6, 7, 8, 9};                //使用數組來定義總線需要的管腳(D0-D7)
 10 int Enable = 10;                        //使能(E)    
 11 
 12 void LcdCommandWrite(int value) {
 13     // 定義所有引腳
 14     int i = 0;
 15     digitalWrite(Enable,LOW);
 16     delayMicroseconds(1);        // 延時1us
 17     digitalWrite(RS, LOW);
 18     digitalWrite(RW, LOW);
 19     
 20     /* 6     7     8     9
 21     *  D7     D6      D5    D4 
 22     *  DB[0] DB[1] DB[2] DB[3]
 23     */
 24     int temp=value & 0xf0;//取指令高4位
 25     for (i=DB[0]; i <= 9; i++)
 26     {
 27         if((temp & 0x80)!=0)//取指令最高位
 28             digitalWrite(i,HIGH);
 29         else
 30             digitalWrite(i,LOW );    
 31         temp <<= 1;
 32     }
 33     delayMicroseconds(1);        // 延時1us
 34     digitalWrite(Enable,HIGH);
 35     delayMicroseconds(1);          // 延時1us
 36     digitalWrite(Enable,LOW);
 37     
 38     temp=(value & 0x0f)<<4;
 39     for (i=DB[0]; i <= 9; i++)
 40     {
 41         if((temp & 0x80)!=0)//取指令最高位
 42             digitalWrite(i,HIGH);
 43         else
 44             digitalWrite(i,LOW );    
 45         temp <<= 1;
 46     }    
 47     delayMicroseconds(1);          // 延時1us
 48     digitalWrite(Enable,HIGH);
 49     delayMicroseconds(1);          // 延時1us
 50     digitalWrite(Enable,LOW);
 51     delayMicroseconds(1);          // 延時1us
 52 }
 53 
 54 void LcdDataWrite(int value) {
 55     // 定義所有引腳
 56     int i = 0;
 57     digitalWrite(Enable,LOW);
 58     delayMicroseconds(1);        // 延時1us
 59     digitalWrite(RS, HIGH);
 60     digitalWrite(RW, LOW);
 61     int temp=value& 0xf0;
 62     for (i=DB[0]; i <= 9; i++)
 63     {
 64         if((temp & 0x80)!=0)//取指令最高位
 65             digitalWrite(i,HIGH);
 66         else
 67             digitalWrite(i,LOW );    
 68         temp <<= 1;
 69     }
 70     digitalWrite(Enable,HIGH);
 71     delayMicroseconds(1);        // 延時1us
 72     digitalWrite(Enable,LOW);
 73 
 74     temp=(value & 0x0f)<<4;
 75     for (i=DB[0]; i <= 9; i++)
 76     {
 77         if((temp & 0x80)!=0)//取指令最高位
 78             digitalWrite(i,HIGH);
 79         else
 80             digitalWrite(i,LOW );    
 81         temp <<= 1;
 82     }
 83     delayMicroseconds(1);        // 延時1us
 84     digitalWrite(Enable,HIGH);
 85     delayMicroseconds(1);        // 延時1us
 86     digitalWrite(Enable,LOW);
 87     delayMicroseconds(1);          // 延時1us
 88 }
 89 
 90 void setup (void) {
 91     int i = 0;
 92     for (i=Enable; i <= RS; i++) {
 93        pinMode(i,OUTPUT);   
 94     }
 95     delay(100);
 96     // 短暫的停頓后初始化LCD
 97     // 用於LCD控制需要
 98     LcdCommandWrite(0x38);         // 設置為8-bit接口,2行顯示,5x7文字大小                     
 99     delay(20);                      
100     LcdCommandWrite(0x06);      // 輸入方式設定,自動增量,畫面沒有移位
101     delay(20);                      
102     LcdCommandWrite(0x0C);      // 顯示設置,開啟顯示屏,光標關,無閃爍
103     delay(20);                                  
104 }
105 
106 void loop (void) {
107   LcdCommandWrite(0x01);          // 屏幕清空,光標位置歸零  
108   delay(10); 
109   LcdCommandWrite(0x80+5);         // 定義光標位置為第一行第五個位置
110   delay(10);                     
111   // 寫入歡迎信息 
112   LcdDataWrite('W');
113   LcdDataWrite('e');
114   LcdDataWrite('l');
115   LcdDataWrite('c');
116   LcdDataWrite('o');
117   LcdDataWrite('m');
118   LcdDataWrite('e');
119   delay(10);
120   LcdCommandWrite(0xc0+2);          // 定義光標位置為第二行第二個位置  
121   delay(10); 
122   LcdDataWrite('I');
123   LcdDataWrite(' ');
124   LcdDataWrite('a');
125   LcdDataWrite('m');
126   LcdDataWrite(' ');
127   LcdDataWrite('D');
128   LcdDataWrite('a');
129   LcdDataWrite('D');
130   LcdDataWrite('a');
131   LcdDataWrite('W');
132   LcdDataWrite('e');
133   LcdDataWrite('i');
134   delay(3000);
135   LcdCommandWrite(0x01);         // 屏幕清空,光標位置歸零
136   delay(10);
137   LcdCommandWrite(0x80+2);         //定義光標位置為第一行第二個位置
138   delay(10);  
139   LcdDataWrite('H');
140   LcdDataWrite('e');
141   LcdDataWrite('l');
142   LcdDataWrite('l');
143   LcdDataWrite('o');
144   LcdDataWrite(' ');
145   LcdDataWrite('W');
146   LcdDataWrite('o');
147   LcdDataWrite('r');
148   LcdDataWrite('l');
149   LcdDataWrite('d');
150   LcdDataWrite('!');
151   LcdCommandWrite(0xc0);          // 定義光標位置為第二行起始位置  
152   delay(10);
153   LcdDataWrite('4');
154   LcdDataWrite('-');
155   LcdDataWrite('B');
156   LcdDataWrite('i');
157   LcdDataWrite('t');
158   LcdDataWrite('-');
159   LcdDataWrite('I');
160   LcdDataWrite('n');
161   LcdDataWrite('t');
162   LcdDataWrite('e');
163   LcdDataWrite('r');
164   LcdDataWrite('f');
165   LcdDataWrite('a');
166   LcdDataWrite('c');
167   LcdDataWrite('e');
168   delay(10); 
169   delay(5000);
170 }

 

2.使用LiquidCrystal庫

 1 /*Arduino在4位接法下使用LiquidCrystal庫
 2 * 輸出歡迎界面和Hello World!
 3 * 作者:大大維
 4 * 2016/10/23
 5 */
 6 #include<LiquidCrystal.h>
 7 LiquidCrystal lcd(13,12,11,10,9,8,7);            //初始化LCD
 8 void setup(){
 9     lcd.begin(16,2);                               //設置LCD為16列*2行
10 }
11 void loop(){
12     lcd.clear();                                //清屏操作
13     lcd.setCursor(5,0);                            //設置光標位置為第一行,第六列
14     lcd.print("Welcome");                        //在LCD上輸出信息
15     delay(10);                                    //延時程序
16     lcd.setCursor(2,1);
17     lcd.print("I am DaDaWei");
18     delay(3000);
19     lcd.clear();
20     lcd.setCursor(2,0);
21     lcd.print("Hello World!");
22     lcd.setCursor(0,1);
23     lcd.print("4-Bit-Interface");
24     delay(5000);
25 }

 

<4>試驗展示

 演示視頻

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM