天天看點

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

接 口

LCD1602是很多單片機愛好者較早接觸的字元型液晶顯示器,它的主要晶片是HD44780或者其它相容晶片。剛開始接觸它的大多是單片機的初學者。由于對它的不了解,不能随心所欲地對它進行驅動。經過一段時間的學習,我對它的驅動有了一點點心得,今天把它記錄在這裡,以備以後查閱。

與此相仿的是LCD12864液晶顯示器,它是一種圖形點陣顯示器,能顯示的内容比LCD1602要豐富得多,除了普通字元外,還可以顯示點陣圖案,帶有漢字庫的還可以顯示漢字,它的并行驅動方式與LCD1602相差無幾,是以,在這裡花點時間是值得的。

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

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖1

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

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖2

它的16條引腳定義如下:

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

表:引腳說明

對表格的說明:

(1)VSS接電源地。

(2)VDD接+5V。

(3)VO是液晶顯示的偏壓信号,可接10K的3296精密電位器,或同樣阻值的RM065/RM063藍白可調電阻。見圖3。

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖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所示。

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖4

基本操作

LCD1602的基本操作分為四種:

  • 讀狀态。輸入RS=0,RW=1,E=高脈沖。輸出:D0—D7為狀态字。
  • 讀資料。輸入RS=1,RW=1,E=高脈沖。輸出:D0—D7為資料。
  • 寫指令。輸入RS=0,RW=0,E=高脈沖。輸出:無。
  • 寫資料。輸入RS=1,RW=0,E=高脈沖。輸出:無。

讀操作時序圖,如圖5所示:

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖5

寫操作時序圖,如圖6所示:

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖6

時序時間參數,如圖7所示:

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖7

DDRAM、CGROM、CGRAM

DDRAM(Display Data RAM)就是顯示資料RAM,用來寄存待顯示的字元代碼。共80個位元組,其位址和螢幕的對應關系如下(如圖8):

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖8

DDRAM相當于計算機的顯存,我們為了在螢幕上顯示字元,就把字元代碼送入顯存,這樣該字元就可以顯示在螢幕上了。同樣LCD1602共有80個位元組的顯存,即DDRAM。但LCD1602的顯示螢幕隻有16×2大小,是以,并不是所有寫入DDRAM的字元代碼都能在螢幕上顯示出來,隻有寫在上圖所示範圍内的字元才可以顯示出來,寫在範圍外的字元不能顯示出來。這樣,我們在程式中可以利用下面的“光标或顯示移動指令”使字元慢慢移動到可見的顯示範圍内,看到字元的移動效果。

前面說了,為了在液晶螢幕上顯示字元,就把字元代碼送入DDRAM。例如,如果想在螢幕左上角顯示字元‘A’,那麼就把字元‘A’的字元代碼41H寫入DDRAM的00H位址處即可。至于怎麼寫入,後面會有說明。

那麼為什麼把字元代碼寫入DDRAM,就可以在相應位置顯示這個代碼的字元呢?我們知道,LCD1602是一種字元點陣顯示器,為了顯示一種字元的字形,必須要有這個字元的字模資料,什麼叫字元的字模資料,看看下面的這個圖就明白了(如圖9)。

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖9

上圖的左邊就是字元‘A’的字模資料,右邊就是将左邊資料用“○”代表0,用“■”代表1。進而顯示出‘A’這個字形。從圖12可以看出,字元‘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中定義的字元也不複存在,下次使用時,必須重新定義。

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖10

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

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖11

圖11說明的是設定CGRAM位址指令。從這個指令的格式中我們可以看出,它共有aaaaaa這6位,一共可以表示64個位址,即64個位元組。一個5×8點陣字元共占用8個位元組,那麼這64個位元組一共可以自定義8個字元。

也就是說,圖11的6位位址中的DB5DB4DB3用來表示8個自定義的字元,DB2DB1DB0用來表示每個字元的8個位元組。這DB5DB4DB3所表示的8個自定義字元(0--7)就是要寫入DDRAM中的字元代碼。我們知道,在CGRAM中隻能定義8個自定義字元,也就是隻有0—7這8個字元代碼,但在下面的這個表(如圖12)中一共有16個字元代碼(××××0000b--××××1111b)。

實際上,如圖11所示,它隻能表示8個自定義字元 (××××0000b=××××1000b, ××××0001b=××××1001b……依次類推)。也就是說,寫入DDRAM中的字元代碼0和字元代碼8是同一個自定義字元。5×10點陣每個字元共占用16個位元組的空間,是以CGRAM中隻能定義4個這樣的自定義字元。

那麼如何在CGRAM中自定義字元呢?在上面的介紹中,我們知道有一個設定CGRAM位址指令,同寫DDRAM指令相似,隻須設定好某個自定義字元的字模資料,然後按照上面介紹的方法,設定好CGRAM位址,依次寫入這個字模資料即可。我們在後面的例子中再進行說明。

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖12

LCD1602指令

1、工作方式設定指令(圖13)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖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)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖14

  • D=1:顯示開,D=0:顯示關。
  • C=1:光标顯示,C=0:光标不顯示。
  • B=1:光标閃爍,B=0:光标不閃爍。

這裡的設定是顯示開,不顯示光标,光标不閃爍,設定字為0x0c。

3、進入模式設定指令(圖15、16)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖15

  • I/D=1:寫入新資料後光标右移。
  • I/D=0:寫入新資料後光标左移。
  • S=1:顯示移動。
  • S=0:顯示不移動。
單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖16

這裡的設定是0x06。

4、光标或顯示移動指令(圖17、18)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖17

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖18

在需要進行整屏移動時,這個指令非常有用,可以實作螢幕的滾動顯示效果。初始化時不使用這個指令。

5、清屏指令(圖19)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖19

清除螢幕顯示内容。光标傳回螢幕左上角。執行這個指令時需要一定時間。

6、光标歸位指令(圖20)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

 圖20

光标傳回螢幕左上角,它不改變螢幕顯示内容。

7、設定CGRAM位址指令(圖21)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖21

這個指令在上面已經介紹過。用法在後面例子中說明。

8、設定DDRAM位址指令(圖22)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖22

這個指令用于設定DDRAM位址。在對DDRAM進行讀寫之前,首先要設定DDRAM位址,然後才能進行讀寫。前面我們說過,DDRAM就是LCD1602的顯示存儲器。我們要在它上面進行顯示,就要把要顯示的字元寫入DDRAM。同樣,我們想知道DDRAM某個位址上有什麼字元,也要先設定DDRAM位址,然後将它讀出到單片機。

9、讀忙信号和位址計數器AC(圖23)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖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)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖24

RS=1,資料;RW=0,寫。指令執行時,要在DB7—DB0上先設定好要寫入的資料,然後執行寫指令。

11、從CGRAM或DDRAM讀資料指令(圖25)

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖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)。

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

圖26

代碼如下:

←左右滑動,檢視代碼→

//File1

#ifndef __ZHANGTYPE_H__

#define __ZHANGTYPE_H__

#define uint8     unsigned char

#define uint16   unsigned short int

#define uint32   unsigned long int

#define int8       signed char

#define int16     signed short int

#define int32     signed long int

#define uint64   unsigned long long int

#define int64     signed long long int

#endif

//File2

#ifndef __FUN_H__

#define __FUN_H__

#include "ZhangType.h"

#include

void Delay(uint16 time);

#endif

//File3

#include "fun.h"

void Delay(uint16 time)

{

    while(time--);

}

//File4

#ifndef __1602_H__

#define __1602_H__

#include

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

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

#define SETMODE  0x38  //16*2顯示,5*7點陣,8位資料接口

#define DISOPEN  0x0C  //顯示開,不顯示光标,光标不閃爍

#define DISMODE  0x06  //讀寫字元後位址加1,屏顯不移動

#define SETADDR  0x80  //設定資料位址指針初始值

#define CLEAR  0x01  //清屏,資料指針清零

#define RET  0x02  //回車,資料指針清零

#define PORT  P2  //I/O口

sbit RS = P1^0;

sbit RW = P1^1;

sbit E = P1^2;

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

void Write1602_Com(uint8 com);  //寫指令

void Write1602_Dat(uint8 dat);  //寫資料

void CheckBusy(void);  //檢查忙

void Write1602_One_Dat(uint8 X,uint8 Y,uint8 dat);

//寫一個資料

void Write1602_Str(uint8 addr,uint8 length,uint8 *pbuf);

//寫一個資料串

#endif//

//File5

#include "1602.h"

void Write1602_Com(uint8 com)

{

    E=0;

    RS=0;  //指令

    Delay(50);  //延時

    RW=0;  //寫

    Delay(50);

    PORT=com;  //端口指派

    Delay(50);

    E=1;  //高脈沖

    Delay(50);

    E=0;

}

void Write1602_Dat(uint8 dat)

{

    E=0;

    RS=1;  //資料

    Delay(50);  //延時

    RW=0;  //寫

    Delay(50);

    PORT=dat;  //端口指派

    Delay(50);

    E=1;  //高脈沖

    Delay(50);

    E=0;

}

void CheckBusy(void)

{

    uint8 temp;

    RS=0;  //指令

    RW=1;  //讀

    E=0;

    while(1)

    {

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

       E=1;  //高脈沖

       temp=PORT;

       E=0;

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

           break;

    }

}

void Init1602(void)

{

    Write1602_Com(SETMODE);  //模式設定

    Delay(500);

    Write1602_Com(DISOPEN);  //顯示設定

    Delay(500);

    Write1602_Com(DISMODE);  //顯示模式

    Delay(500);

    Write1602_Com(CLEAR);  //清屏

    Delay(500);

}

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

{

    x&=0x0f;

    y&=0x01;

    if(y)

       x|=0x40;

    x|=0x80;

    Write1602_Com(x);

    Write1602_Dat(dat);

}

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

{

    uint8 i;

    Write1602_Com(addr);

    for(i=0;i

    {

       Write1602_Dat(pbuf[i]);

    }

}

//File6

#include "1602.h"

#include "fun.h" 

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

0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00

};

uint8 code pi[8]={

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

};

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

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

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

uint8 i;

void main()

{

    Init1602();  //初始化1602

    //自定義CGRAM

    Write1602_Str(0x40,8,hot);  //攝氏溫标

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

    Write1602_Str(0x80,strlen(strMCU),strMCU);

    //"I love MCU!"

    Write1602_Str(0x80+0x40,strlen(strTest),strTest);

    //"LCD1602 Test!"

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

       Delay(10000);

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

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

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

       Write1602_Dat(0);

    Write1602_Com(0xc0);  //設定DDRAM位址

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

       Write1602_Dat(1);

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

       Delay(10000);

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

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

    Write1602_Str(0x80+0x10,strlen(blog),blog);

    //寫在顯示之外

    while(1)

    {

       Write1602_Com(0x18);  //左移

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

           Delay(10000);

    }

}

本文系網絡轉載,版權歸原作者所有,如有侵權請聯系删除

單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...
單片機8×8點陣顯示簡單漢字的程式_LCD1602驅動講解,超詳細,單片機新手必看...

掃碼入群 掃碼添加管理者微信

加入“電子産品世界”粉絲交流群

↓↓↓↓點選,檢視更多新聞