久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8266|回復: 1
收起左側

LCD1602液晶顯示應用總結

[復制鏈接]
ID:113629 發表于 2016-4-12 19:36 | 顯示全部樓層 |閱讀模式
轉自:http://www.zg4o1577.cn/mcu/4327.html


一.接口

LCD1602是很多單片機愛好者較早接觸的字符型液晶顯示器,它的主控芯片是HD44780或者其它兼容芯片。剛開始接觸它的大多是單片機的初學者。由于對它的不了解,不能隨心所欲地對它進行驅動。經過一段時間的學習,我對它的驅動有了一點點心得,今天把它記錄在這里,以備以后查閱。與此相仿的是LCD12864液晶顯示器,它是一種圖形點陣顯示器,能顯示的內容比LCD1602要豐富得多,除了普通字符外,還可以顯示點陣圖案,帶有漢字庫的還可以顯示漢字,它的并行驅動方式與LCD1602相差無幾,所以,在這里花點時間是值得的。

一般來說,LCD1602有16條引腳,據說還有14條引腳的,與16腳的相比缺少了背光電源A(15腳)和地線K(16腳)。我手里這塊LCD1602的型號是HJ1602A,是繪晶科技公司的產品,它有16條引腳。如圖1所示:



圖1

再來一張它的背面的,如圖2所示:



圖2

它的16條引腳定義如下:

            
引腳號
            
            
符號
            
            
引腳說明
            
            
引腳號
            
            
符號
            
            
引腳說明
            
            
1
            
            
VSS
            
            
電源地
            
            
9
            
            
D2
            
            
數據端口
            
            
2
            
            
VDD
            
            
電源正極
            
            
10
            
            
D3
            
            
數據端口
            
            
3
            
            
VO
            
            
偏壓信號
            
            
11
            
            
D4
            
            
數據端口
            
            
4
            
            
RS
            
            
命令/數據
            
            
12
            
            
D5
            
            
數據端口
            
            
5
            
            
RW
            
            
讀/寫
            
            
13
            
            
D6
            
            
數據端口
            
            
6
            
            
E
            
            
使能
            
            
14
            
            
D7
            
            
數據端口
            
            
7
            
            
D0
            
            
數據端口
            
            
15
            
            
A
            
            
背光正極
            
            
8
            
            
D1
            
            
數據端口
            
            
16
            
            
K
            
            
背光負極
            
對這個表的說明:
1.    VSS接電源地。
2.    VDD接+5V。
3.    VO是液晶顯示的偏壓信號,可接10K的3296精密電位器。或同樣阻值的RM065/RM063藍白可調電阻。見圖3。

圖3
4.    RS是命令/數據選擇引腳,接單片機的一個I/O,當RS為低電平時,選擇命令;當RS為高電平時,選擇數據。
5.    RW是讀/寫選擇引腳,接單片機的一個I/O,當RW為低電平時,向LCD1602寫入命令或數據;當RW為高電平時,從LCD1602讀取狀態或數據。如果不需要進行讀取操作,可以直接將其接VSS。
6.    E,執行命令的使能引腳,接單片機的一個I/O。
7.    D0—D7,并行數據輸入/輸出引腳,可接單片機的P0—P3任意的8個I/O口。如果接P0口,P0口應該接4.7K—10K的上拉電阻。如果是4線并行驅動,只須接4個I/O口。
8.    A背光正極,可接一個10—47歐的限流電阻到VDD。
9.    K背光負極,接VSS。見圖4所示。

圖4
二.基本操作
LCD1602的基本操作分為四種:
1.    讀狀態:輸入RS=0,RW=1,E=高脈沖。輸出:D0—D7為狀態字。
2.    讀數據:輸入RS=1,RW=1,E=高脈沖。輸出:D0—D7為數據。
3.    寫命令:輸入RS=0,RW=0,E=高脈沖。輸出:無。
4.    寫數據:輸入RS=1,RW=0,E=高脈沖。輸出:無。
讀操作時序圖(如圖5):

圖5
寫操作時序圖(如圖6):

圖6
時序時間參數(如圖7):

圖7
三.DDRAM、CGROM和CGRAM
DDRAM(Display Data RAM)就是顯示數據RAM,用來寄存待顯示的字符代碼。共80個字節,其地址和屏幕的對應關系如下(如圖8):

圖8
DDRAM相當于計算機的顯存,我們為了在屏幕上顯示字符,就把字符代碼送入顯存,這樣該字符就可以顯示在屏幕上了。同樣LCD1602共有80個字節的顯存,即DDRAM。但LCD1602的顯示屏幕只有16×2大小,因此,并不是所有寫入DDRAM的字符代碼都能在屏幕上顯示出來,只有寫在上圖所示范圍內的字符才可以顯示出來,寫在范圍外的字符不能顯示出來。這樣,我們在程序中可以利用下面的“光標或顯示移動指令”使字符慢慢移動到可見的顯示范圍內,看到字符的移動效果。
前面說了,為了在液晶屏幕上顯示字符,就把字符代碼送入DDRAM。例如,如果想在屏幕左上角顯示字符‘A’,那么就把字符‘A’的字符代碼41H寫入DDRAM的00H地址處即可。至于怎么寫入,后面會有說明。那么為什么把字符代碼寫入DDRAM,就可以在相應位置顯示這個代碼的字符呢?我們知道,LCD1602是一種字符點陣顯示器,為了顯示一種字符的字形,必須要有這個字符的字模數據,什么叫字符的字模數據,看看下面的這個圖就明白了(如圖9)。

圖9
上圖的左邊就是字符‘A’的字模數據,右邊就是將左邊數據用“○”代表0,用“■”代表1。從而顯示出‘A’這個字形。從下面的圖可以看出,字符‘A’的高4位是0100,低4位是0001,合在一起就是01000001b,即41H。它恰好與該字符的ASCII碼一致,這樣就給了我們很大的方便,我們可以在PC上使用P2=‘A’這樣的語法。編譯后,正好是這個字符的字符代碼。
在LCD1602模塊上固化了字模存儲器,就是CGROM和CGRAM,HD44780內置了192個常用字符的字模,存于字符產生器CGROM(Character Generator ROM)中,另外還有8個允許用戶自定義的字符產生RAM,稱為CGRAM(Character Generator RAM)。下圖(如圖12)說明了CGROM和CGRAM與字符的對應關系。從ROM和RAM的名字我們也可以知道,ROM是早已固化在LCD1602模塊中的,只能讀取;而RAM是可讀寫的。也就是說,如果只需要在屏幕上顯示已存在于CGROM中的字符,那么只須在DDRAM中寫入它的字符代碼就可以了;但如果要顯示CGROM中沒有的字符,比如攝氏溫標的符號,那么就只有先在CGRAM中定義,然后再在DDRAM中寫入這個自定義字符的字符代碼即可。和CGROM中固化的字符不同,CGRAM中本身沒有字符,所以要在DDRAM中寫入某個CGROM不存在的字符,必須在CGRAM中先定義后使用。程序退出后CGRAM中定義的字符也不復存在,下次使用時,必須重新定義。

圖10
上面這個圖(如圖10)說明的是5×8點陣和5×10點陣字符的字形和光標的位置。先來說5×8點陣,它有8行5列。那么定義這樣一個字符需要8個字節,每個字節的前3個位沒有被使用。例如,定義攝氏溫標的符號{0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00}。

圖11
上面這個圖(如圖11)說明的是設置CGRAM地址指令。從這個指令的格式中我們可以看出,它共有aaaaaa這6位,一共可以表示64個地址,即64個字節。一個5×8點陣字符共占用8個字節,那么這64個字節一共可以自定義8個字符。也就是說,上面這個圖的6位地址中的DB5DB4DB3用來表示8個自定義的字符,DB2DB1DB0用來表示每個字符的8個字節。這DB5DB4DB3所表示的8個自定義字符(0--7)就是要寫入DDRAM中的字符代碼。我們知道,在CGRAM中只能定義8個自定義字符,也就是只有0—7這8個字符代碼,但在下面的這個表(如圖12)中一共有16個字符代碼(××××0000b--××××1111b)。實際上,如圖所示,它只能表示8個自定義字符 (××××0000b=××××1000b, ××××0001b=××××1001b……依次類推)。也就是說,寫入DDRAM中的字符代碼0和字符代碼8是同一個自定義字符。 5×10點陣每個字符共占用16個字節的空間,所以CGRAM中只能定義4個這樣的自定義字符。
那么如何在CGRAM中自定義字符呢?在上面的介紹中,我們知道有一個設置CGRAM地址指令,同寫DDRAM指令相似,只須設置好某個自定義字符的字模數據,然后按照上面介紹的方法,設置好CGRAM地址,依次寫入這個字模數據即可。我們在后面的例子中再進行說明。

圖12
四.LCD1602指令
1.工作方式設置指令(如圖13)

圖13
×:不關心,也就是說這個位是0或1都可以,一般取0。
DL:設置數據接口位數。
DL=1:8位數據接口(D7—D0)。
DL=0:4位數據接口(D7—D4)。
N=0:一行顯示。
N=1:兩行顯示。
F=0:5×8點陣字符。
F=1:5×10點陣字符。
說明:因為是寫指令字,所以RS和RW都是0。LCD1602只能用并行方式驅動,不能用串行方式驅動。而并行方式又可以選擇8位數據接口或4位數據接口。這里我們選擇8位數據接口(D7—D0)。我們的設置是8位數據接口,兩行顯示,5×8點陣,即0b00111000也就是0x38。(注意:NF是10或11的效果是一樣的,都是兩行5×8點陣。因為它不能以兩行5×10點陣方式進行顯示,換句話說,這里用0x38或0x3c是一樣的)。
2.顯示開關控制指令(如圖14)

圖14
D=1:顯示開,D=0:顯示關。
C=1:光標顯示,C=0:光標不顯示。
B=1:光標閃爍,B=0:光標不閃爍。
說明:這里的設置是顯示開,不顯示光標,光標不閃爍,設置字為0x0c。
3.進入模式設置指令(如圖15、16)

圖15
I/D=1:寫入新數據后光標右移。
I/D=0:寫入新數據后光標左移。
S=1:顯示移動。
S=0:顯示不移動。

圖16
說明:這里的設置是0x06。
4.光標或顯示移動指令(如圖17、18)

圖17

圖18
說明:在需要進行整屏移動時,這個指令非常有用,可以實現屏幕的滾動顯示效果。初始化時不使用這個指令。
5.清屏指令(如圖19)

圖19
說明:清除屏幕顯示內容。光標返回屏幕左上角。執行這個指令時需要一定時間。
6.光標歸位指令(如圖20)
圖20
說明:光標返回屏幕左上角,它不改變屏幕顯示內容。
7.設置CGRAM地址指令(如圖21)

圖21
說明:這個指令在上面已經介紹過。用法在后面例子中說明。
8.設置DDRAM地址指令(如圖22)

圖22
說明:這個指令用于設置DDRAM地址。在對DDRAM進行讀寫之前,首先要設置DDRAM地址,然后才能進行讀寫。前面我們說過,DDRAM就是LCD1602的顯示存儲器。我們要在它上面進行顯示,就要把要顯示的字符寫入DDRAM。同樣,我們想知道DDRAM某個地址上有什么字符,也要先設置DDRAM地址,然后將它讀出到單片機。
9.讀忙信號和地址計數器AC(如圖23)

圖23
說明:這個指令用來讀取LCD1602狀態。對于單片機來說,LCD1602屬于慢速設備。當單片機向其發送一個指令后,它將去執行這個指令。這時如果單片機再次發送下一條指令,由于LCD1602速度較慢,前一條指令還未執行完畢,它將不接受這新的指令,導致新的指令丟失。因此這條讀忙指令可以用來判斷LCD1602是否忙,能否接收單片機發來的指令。當BF=1,表示LCD1602正忙,不能接受單片機的指令;當BF=0,表示LCD1602空閑,可以接收單片機的指令。RS=0,表示是指令;RW=1,表示是讀取。這條指令還有一個副產品:即可以得到地址記數器AC的值(address counter)。LCD1602維護了一個地址計數器AC,用來記錄下一次讀寫CGRAM或DDRAM的位置。需要強調的是:這條指令我一次也沒有執行成功。很多網友似乎也是這樣。好在我們有另外的辦法,也就是延時。通過查看每條指令的執行時間,再經過一些試驗,可以確定指令的延時。這樣就可以在上一條指令執行完畢后再執行下一條指令了。
10.寫數據到CGRAM或DDRAM指令(如圖24)

圖24
說明:RS=1,數據;RW=0,寫。指令執行時,要在DB7—DB0上先設置好要寫入的數據,然后執行寫命令。
11.從CGRAM或DDRAM讀數據指令(如圖25)

圖25
說明:RS=1,數據;RW=1,讀。先設置好CGRAM或DDRAM的地址,然后執行讀取命令。數據就被讀入后DB7—DB0。
五.實例
下面我們就以一個實例來結束這篇文章。先介紹一下背景:單片機最小系統(擴充了外部RAM 62256)。采用STC89C52RC,晶振22.1184MHZ。以5×8點陣,16×2行,8位數據端口。首先在第一行顯示“I love MCU!”,第二行顯示“LCD1602 Test!”。延時一段時間,清屏。然后在第一行顯示自定義字符:攝氏溫標標志。第二行顯示圓周率(pai)標志。再延時一段時間,清屏。最后在第一行顯示“Welcome to my blog!”,顯示方式是從屏幕右面移入,左面移出。周而復始(如圖26)。

圖26
//File1
  1. #ifndef __ZHANGTYPE_H__

  2. #define __ZHANGTYPE_H__



  3. #define uint8    unsigned char

  4. #define uint16   unsigned short int

  5. #define uint32   unsigned long int

  6. #define int8     signed char

  7. #define int16    signed short int

  8. #define int32    signed long int

  9. #define uint64   unsigned long long int

  10. #define int64    signed long long int



  11. #endif

  12. //File2



  13. #ifndef __FUN_H__

  14. #define __FUN_H__

  15. #include "ZhangType.h"

  16. #include  

  17. void Delay(uint16 time);

  18. #endif

  19. //File3



  20. #include "fun.h"

  21. void Delay(uint16 time)

  22. {

  23.     while(time--);

  24. }

  25. //File4



  26. #ifndef __1602_H__

  27. #define __1602_H__



  28. #include

  29. #include "ZhangType.h"          //變量類型

  30. #include "fun.h"            //常用函數



  31. #define    SETMODE    0x38          //16*2顯示,5*7點陣,8位數據接口

  32. #define DISOPEN   0x0C          //顯示開,不顯示光標,光標不閃爍

  33. #define DISMODE   0x06          //讀寫字符后地址加1,屏顯不移動

  34. #define    SETADDR    0x80          //設置數據地址指針初始值

  35. #define CLEAR 0x01          //清屏,數據指針清零

  36. #define RET       0x02          //回車,數據指針清零

  37. #define PORT  P2            //I/O口



  38. sbit RS = P1^0;

  39. sbit RW = P1^1;

  40. sbit E = P1^2;



  41. void Init1602(void);        //初始化1602

  42. void Write1602_Com(uint8 com);  //寫命令

  43. void Write1602_Dat(uint8 dat);  //寫數據

  44. void CheckBusy(void);           //檢查忙

  45. void Write1602_One_Dat(uint8 X,uint8 Y,uint8 dat);          //寫一個數據

  46. void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf);    //寫一個數據串

  47. #endif//

  48. //File5



  49. #include "1602.h"



  50. void Write1602_Com(uint8 com)

  51. {

  52.     E=0;

  53.     RS=0;                    //命令

  54.     Delay(50);               //延時

  55.     RW=0;                    //寫         

  56.     Delay(50);

  57.     PORT=com;                //端口賦值

  58.     Delay(50);

  59.     E=1;                     //高脈沖

  60.     Delay(50);

  61.     E=0;

  62. }



  63. void Write1602_Dat(uint8 dat)

  64. {

  65.     E=0;

  66.     RS=1;                    //數據

  67.     Delay(50);               //延時

  68.     RW=0;                    //寫

  69.     Delay(50);

  70.     PORT=dat;                //端口賦值

  71.     Delay(50);

  72.     E=1;                     //高脈沖

  73.     Delay(50);

  74.     E=0;

  75. }



  76. void CheckBusy(void)

  77. {

  78.     uint8 temp;

  79.     RS=0;                    //命令

  80.     RW=1;                    //讀

  81.     E=0;

  82.     while(1)

  83.     {

  84.        PORT=0xFF;           //端口為輸入

  85.        E=1;                 //高脈沖

  86.        temp=PORT;

  87.        E=0;

  88.        if ((temp&0x80)==0)      //檢查BF位是否為0

  89.            break;

  90.     }

  91. }



  92. void Init1602(void)

  93. {

  94.     Write1602_Com(SETMODE);     //模式設置

  95.     Delay(500);

  96.     Write1602_Com(DISOPEN);     //顯示設置

  97.     Delay(500);

  98.     Write1602_Com(DISMODE);     //顯示模式

  99.     Delay(500);

  100.     Write1602_Com(CLEAR);       //清屏

  101.     Delay(500);

  102. }



  103. void Write1602_One_Dat(uint8 x,uint8 y,uint8 dat)

  104. {

  105.     x&=0x0f;

  106.     y&=0x01;

  107.     if(y)

  108.        x|=0x40;

  109.     x|=0x80;

  110.     Write1602_Com(x);

  111.     Write1602_Dat(dat);

  112. }



  113. void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf)

  114. {

  115.     uint8 i;

  116.     Write1602_Com(addr);

  117.     for(i=0;i

  118.     {

  119.        Write1602_Dat(pbuf[i]);

  120.     }

  121. }

  122. //File6

  123. *******************************************************

  124. *名稱:主文件(_main.c)

  125. *功能:測試

  126. *日期:2014/09/09

  127. *******************************************************/

  128. #include "1602.h"

  129. #include "fun.h"

  130. uint8 code hot[8]={                                  //攝氏溫度字模

  131. 0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00

  132. };

  133. uint8 code pi[8]={                       

  134. 0x00,0x1f,0x0a,0x0a,0x0a,0x13,0x00,0x00                 //pai

  135. };

  136. uint8 code strMCU[]="I love MCU!";

  137. uint8 code strTest[]="LCD1602 Test!";

  138. uint8 code blog[]="Welcome to my blog!";

  139. uint8 i;

  140. void main()

  141. {

  142.     Init1602();                                      //初始化1602

  143.     //自定義CGRAM

  144.     Write1602_Str(0x40,8,hot);                       //攝氏溫標

  145.     Write1602_Str(0x48,8,pi);                        //pai



  146.     Write1602_Str(0x80,strlen(strMCU),strMCU);           //"I love MCU!"

  147.     Write1602_Str(0x80+0x40,strlen(strTest),strTest);    //"LCD1602 Test!"



  148.     for(i=0;i<50;i++)                             //延時一段時間

  149.        Delay(10000);



  150.     Write1602_Com(CLEAR);                            //指令執行時間較長

  151.     Delay(500);                                      //多加一些延時

  152.     for(i=0;i<16;i++)

  153.        Write1602_Dat(0);

  154.    

  155.     Write1602_Com(0xc0);                          //設置DDRAM地址

  156.     for(i=0;i<16;i++)

  157.        Write1602_Dat(1);

  158.     for(i=0;i<50;i++)                             //延時一段時間

  159.        Delay(10000);

  160.    

  161.     Write1602_Com(CLEAR);                            //指令執行時間較長

  162.     Delay(500);                                      //多加一些延時

  163.     Write1602_Str(0x80+0x10,strlen(blog),blog);          //寫在顯示之外

  164.     while(1)

  165.     {

  166.        Write1602_Com(0x18);                      //左移

  167.        for(i=0;i<20;i++)                         //延時

  168.            Delay(10000);

  169.     }

  170. }

  171. //############################# THE END #############################
復制代碼


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:227688 發表于 2017-12-5 12:11 | 顯示全部樓層
感謝分享  很不錯
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 视频一区 国产精品 | 欧美又大粗又爽又黄大片视频 | 中文字幕在线二区 | 毛片站 | 成年人免费看 | 在线观看国产三级 | 国产91在线 | 中日 | 国产在线一区二 | 国产精品久久久久久婷婷天堂 | 日韩高清一区 | 亚洲电影一区二区三区 | 自拍偷拍中文字幕 | 日韩在线免费视频 | 日本一区高清 | av天天干 | 亚洲精品亚洲人成人网 | 久久中文字幕视频 | 欧美一区永久视频免费观看 | 精品91久久久 | 中文字幕亚洲区 | 国产激情一区二区三区 | 一区中文字幕 | 在线国产一区 | 91婷婷韩国欧美一区二区 | 久久九精品| 国产精品亚洲欧美日韩一区在线 | 91福利在线观看视频 | 91九色视频| 天堂在线一区 | 视频二区在线观看 | 在线欧美日韩 | 国产欧美日韩一区 | 黄色免费观看 | 久久精品国产久精国产 | 久久久.com| 九九色九九 | 国产一区视频在线 | 毛片免费观看 | 爱高潮www亚洲精品 中文字幕免费视频 | 玖玖国产精品视频 | 成人免费一区二区 |