11.1 1602 液晶顯示模塊簡介
1602 液晶顯示模塊是一種通用的工業(yè)液晶顯示模塊,專門用來顯示字母、數(shù)字、符號等的點陣型液晶顯示模塊。從名字就可以看出該液晶顯示模塊有 2 行,每行 16 個字符共可以顯示 32 個字符。每個字符是由 5x7 或者 5x11 的點陣位組成,我們這里講解的為 5x7 模式的模塊。模塊顯示界面結(jié)構(gòu)尺寸如下圖所示:
與數(shù)碼管相比,不需周期性的對顯示進行刷新,只需將需要顯示的字符按照時序要求發(fā)送給 1602 液晶顯示模塊便可一直顯示,有效的節(jié)省了單片機的系統(tǒng)資源。通過單片機控制 1602 的讀寫硬件( RS, RW)進行控制,根據(jù)相應(yīng)的時序?qū)?shù)據(jù) D0-D7 進行操作便可實現(xiàn)顯示指定的字符。1602 模塊共有 16 個引腳,各引腳定義如下圖所示:
- 第 1,2 引腳:VDD、VS S 為 1602 供電的正負(fù)極,最佳供電電壓為 5V。
- 第 3 引腳:VL 液晶顯示偏壓信號,即為顯示屏的對比度調(diào)節(jié)端,當(dāng)接電源時對比度最高,接低時對比對最低,在使用中往往通過接一個可變電阻來調(diào)節(jié)顯示對比度。
- 第 4 引腳:RS 為數(shù)據(jù)/命令選擇端,當(dāng) RS=1 時,選擇操作 1602 內(nèi)部的數(shù)據(jù)寄存器,當(dāng) RS=0 時,選擇操作內(nèi)部指令寄存器。
- 第 5 引腳:R/W 為讀寫選擇端,當(dāng) R/W=1 時,對 1602 進行讀數(shù)據(jù)操作,當(dāng) R/W=0 時,對 1602 進行寫操作。
- 第 6 引腳:E 為 1602 液晶顯示模塊使能端,與 RS,R/W 配合使用在高電平時讀取信息,負(fù)跳變時執(zhí)行指令。
- 第 7-14 引腳:為 8 位的雙向數(shù)據(jù)端口 D0~D7。
- 第 15,16 引腳:BLA 背光源正極,BLK 背光源負(fù)極。BLK 接地,BLA 接電源 VDD 時,1602 液晶背光點亮,接 GND 時,背光熄滅。
RY-51 單片機開發(fā)板 1602 液晶顯示模塊的電路連接圖如下圖所示:
如上圖所示,1602 的 4,5,6 引腳分別接到到了單片機的 P3.4-P3.6 端口,數(shù)據(jù)端口 D0-D7 鏈接到單片機的 P0 端口與 RY-51 開發(fā)板的 8 位數(shù)碼管共用 P1 端口,因此,在應(yīng)用 1602 液晶顯示模塊的時候首先要關(guān)閉數(shù)碼管。
11.2 1602 讀、寫操作時序解析
剛開始接觸 1602 液晶顯示模塊的時候可能會覺得有一點難度,感覺挺復(fù)雜,理解起來比較費勁。其實,只要掌握了的操作規(guī)律,多次的練習(xí)之后你會發(fā)現(xiàn)其實很簡單。我們要實現(xiàn)對單片機的操作無非就是 1602 的初始化、對 1602 的讀操作、寫操作。對 1602 液晶顯示的一切都是建立在數(shù)據(jù)的讀、寫操作之上了,因此,我們只要研究明白了讀、寫的操作時序,掌握它的應(yīng)用就非常簡單了。通過查找 1602 的數(shù)據(jù)手冊,讀、寫時序如下圖所示:
讀操作時序解析如下:
將 R/W 拉高進入讀操作模式,同時 RS 要么為高電平要么為低電平,高電平時為讀數(shù)據(jù)操作,低電平時為讀狀態(tài)操作,經(jīng)過 tSP1 時間之后才可將使能信號 E 拉高,并且 E 的高電平維持時間為 tPW,在使能信號 E 拉高之后不超過 tD 時間內(nèi),1602 液晶顯示器將數(shù)據(jù)放在 DB0~DB7 數(shù)據(jù)線上。這時我們將數(shù)據(jù)讀取并將使能 E 拉低,整個數(shù)據(jù)或狀態(tài)的讀取就完成了。
那么,我們在將某個信號拉高或者拉低需要滿足上面一些時間的先后順序要求。例如我們以讀 1602 狀態(tài)為例,第一條語句首先將 RS 拉低,即 RS = 0,然后將 R/W 拉高,即 R/W=1,接下來將使能信號 E 高,即 E=1,上面兩條語句的時間間隔要求不低于 tSP1,查詢數(shù)據(jù)表格可知 tSP1 最小值為 30ns,而我們開發(fā)板執(zhí)行一條語句的時間大約為 1us,因此遠(yuǎn)遠(yuǎn)能滿足要求,如果我們在執(zhí)行語句比較快的系統(tǒng)運行時,為了保證時序要求,可以在兩條語句之間插入軟件延時。E 的高電平維持時間 tPW 最小值為 150ns,而我們 E 維持高電平約為 1us,滿足要求。tD 最大值為 100ns,因此,可以直接將數(shù)據(jù)讀取,接著將 E 拉低完成狀態(tài)讀取,我們將代碼放到函數(shù)當(dāng)中,返回值為讀取的狀態(tài)數(shù)據(jù),應(yīng)用的時候只需調(diào)用該函數(shù)即可,代碼如下:
unsigned char RD_sta()//讀狀態(tài)函數(shù)
{
unsigned char sta;
RS_1602 = 0;
RW_1602 = 1;//進入讀1602狀態(tài)模式
EN_1602 = 1;//拉高使能信號
sta = P0; //將1602狀態(tài)數(shù)據(jù)讀取
EN_1602 = 0;//拉低使能,完成讀操作
return sta; //將狀態(tài)值返
}
寫操作時序與讀操作的基本一致,唯一不同的是,在使能信號 E 拉高之前 tSP2 單片機必須把需要學(xué)的數(shù)據(jù)送到數(shù)據(jù)端口上。當(dāng) RS=1 時,表示將要往 1602 寫數(shù)據(jù),當(dāng) RS=0 時,表示將要往 1602 里面寫指令。
LCD1602 時序參數(shù)如下圖所示:
我們分別把寫數(shù)據(jù)、寫指令分別放到函數(shù) WR_Cmd(unsigned char cmd)、 WR_Dat(unsigned char dat)中。
void WR_Cmd(unsigned char cmd)//寫指令函數(shù)
{
Ready(); //檢測1602是否處于空閑狀態(tài)
RS_1602 = 0;
RW_1602 = 0;//進入寫指令模式
P0 = cmd; //將指令數(shù)據(jù)輸出
EN_1602 = 1;//拉高使能信號
EN_1602 = 0;//拉低使能,完成寫操作
}
void WR_Dat(unsigned char dat)//寫數(shù)據(jù)函數(shù)
{
Ready(); //檢測1602是否處于空閑狀態(tài)
RS_1602 = 1;
RW_1602 = 0;//進入寫數(shù)據(jù)模式
P0 = dat; //將數(shù)據(jù)輸出
EN_1602 = 1;//拉高使能信號
EN_1602 = 0;//拉低使能,完成寫操作
}
在上述函數(shù)中,增加了一個 Ready()函數(shù),這個函數(shù)的作用為先查詢 1602 是否處于空閑狀態(tài),當(dāng)為空閑狀態(tài)時,才開始寫操作。到目前為止,我們已經(jīng)完成了對 1602 最底層的數(shù)據(jù)讀寫操作,下面我們只要按照數(shù)據(jù)手冊的要求調(diào)用這三個函數(shù)便可實現(xiàn)各種類型的顯示功能。對于 1602 而言,讀狀態(tài)函數(shù) RD_sta(),的返回值數(shù)據(jù)格式如下:
如上表所示,返回狀態(tài)字的低六位為當(dāng)前數(shù)據(jù)地址指針的數(shù)值,最高位讀寫操作使能,當(dāng)返回值為 1 時,表示 1602 正處于忙的狀態(tài),不允許讀寫操作,當(dāng)返回值為 0 時,表示可以對 1602 進行讀寫,因此,在讀寫前進行判斷,我們將忙檢測函數(shù)如下:
void Ready() //空閑檢測函數(shù)
{
P0 = 0xFF;//P0端口設(shè)置為輸入時,先賦值0xFF
while(RD_sta() & 0x80);//bit7等于1表示忙,一直檢測到0為止
}
11.3 1602 液晶顯示初始化
在使用 1602 進行顯示前時,首先要通過寫一系列的指令對 1602 進行初始化,各指令碼及功能定義如下所示:
初始化如下:
- 寫指令 38H:設(shè)置 16x2 顯示,5x7 點陣,8 位數(shù)據(jù)接口;
- 寫指令 0CH:開顯示,關(guān)閉光標(biāo);
- 寫指令 06H:讀或?qū)懲暌粋€字符后,地址指針、光標(biāo)均加 1;
- 寫指令 01H:數(shù)據(jù)指針清零、所示顯示清零
將初始化程序放到初始化函數(shù) Init_1602()中,代碼如下圖所示:
void Init_1602() //1602初始化函
{
WR_Cmd(0x38);//設(shè)置16x2顯示,5x7點陣,8位數(shù)據(jù)接口
WR_Cmd(0x0C);//開顯示,關(guān)閉光標(biāo)
WR_Cmd(0x06);//讀或?qū)懲暌粋€字符后,地址指針、光標(biāo)均加1
WR_Cmd(0x01);//數(shù)據(jù)指針清零、所示顯示清零
}
11.4 1602 液晶顯示字符操作
當(dāng)我們開始要往 1602 里面寫字符的時候,我們首先得告訴 1602 我們要從哪個地方開始寫,也就是寫數(shù)據(jù)開始地址,1602 共可以顯示 2 行 32 個字符,那么每個字符的地址是多少呢?1602 內(nèi)部控制器有 80 字節(jié)的 RAM 緩沖區(qū),RAM 地址與 1602 顯示模塊的對應(yīng)關(guān)系如下圖所示:
如圖所示,地址 00H-0FH 的 RAM 與顯示模塊的第一行一一對應(yīng)。地址 40H~4FH 的 RAM 與顯示模塊的第二行一一對應(yīng)。這里要特別注意的是,第一行到第二行的地址不是連續(xù)的。通過寫指令可以告訴 1602 我們將要從哪里開始寫字符了,寫地址指令碼及功能定義如下表所示:
例如,若需要往第二行的第一列開始寫字符,首先應(yīng)該寫指令 WR_Cmd(0x80 + 0x40)。接下通過調(diào)用寫數(shù)據(jù)函數(shù) WR_Dat(dat)將對應(yīng)的字符顯示到 1602 了。寫數(shù)據(jù)函數(shù)中的 dat 為字符對應(yīng)的字符碼,字符碼可以通過查詢 1602 的標(biāo)準(zhǔn)字符庫,如下圖所示,行坐標(biāo)為字符碼的低 4 位,縱坐標(biāo)為字符碼的高四位。例如,我們要將“C”顯示到 1602,需要調(diào)用 WR_Dat(0x43)完成顯示。標(biāo)準(zhǔn) 1602 字符字庫如下:
將顯示字符的步驟寫到函數(shù)中,函數(shù)的功能為:從第 row 行,第 column 列開始顯示字符串 str,函數(shù)代碼如圖所示:
//字符串顯示功能:從第row行,第column列開始顯示字符串str
void Disp_1602_str(unsigned char row,unsigned char column,char *str)
{
unsigned char addr;
addr = (row-1)*0x40 + (column-1);//組合成地址
WR_Cmd(0x80+addr);//寫地址命令
while(*str)//判斷str字符串是否已結(jié)束
{
WR_Dat(*str++);//將str字符串?dāng)?shù)據(jù)依次寫入
}
}
11.5 1602 顯示應(yīng)用實例
我們結(jié)合上面講解的各個函數(shù),實現(xiàn)從 1602 液晶顯示模塊第 1 行第 3 列開始顯示字符串“RongYi RY-51”。由于 RY-51 開發(fā)板的 8 個數(shù)碼管與 1602 共用 P0 口,因此在主程序開始處將數(shù)碼管關(guān)閉,接著初始化 1602,然后顯示字符串,最后進入死循環(huán)。程序代碼如下:
#include < reg52.h >
sbit DU = P2^7;//數(shù)碼管段選、位選引腳定義
sbit WE = P2^6;
sbit RS_1602 = P3^4; //1602,RS、R/W,E引腳定義
sbit RW_1602 = P3^5;
sbit EN_1602 = P3^6;
//字符串顯示函數(shù)聲明
void Disp_1602_str(unsigned char row,unsigned char column,char *str);
void Init_1602();//1602初始化函數(shù)聲明
void Ready();//空閑檢測函數(shù)聲明
void WR_Cmd(unsigned char cmd);//寫指令函數(shù)聲明
void WR_Dat(unsigned char dat);//寫數(shù)據(jù)函數(shù)聲明
unsigned char RD_sta();//讀狀態(tài)函數(shù)聲明
void main()
{
P0 = 0;//關(guān)閉所有數(shù)碼管
WE = 1;
WE = 0;
Init_1602();//1602初始化
Disp_1602_str(1,3,"RongYi RY-51");//第1行第3列開始顯示"RongYi RY-51"
while(1);
}
//字符串顯示功能:從第row行,第column列開始顯示字符串str
void Disp_1602_str(unsigned char row,unsigned char column,char *str)
{
unsigned char addr;
addr = (row-1)*0x40 + (column-1);//組合成地址
WR_Cmd(0x80+addr);//寫地址命令
while(*str)//判斷str字符串是否已結(jié)束
{
WR_Dat(*str++);//將str字符串?dāng)?shù)據(jù)依次寫入
}
}
void Init_1602() //1602初始化函
{
WR_Cmd(0x38);//設(shè)置16x2顯示,5x7點陣,8位數(shù)據(jù)接口
WR_Cmd(0x0C);//開顯示,關(guān)閉光標(biāo)
WR_Cmd(0x06);//讀或?qū)懲暌粋€字符后,地址指針、光標(biāo)均加1
WR_Cmd(0x01);//數(shù)據(jù)指針清零、所示顯示清零
}
void Ready() //空閑檢測函數(shù)
{
P0 = 0xFF;//P0端口設(shè)置為輸入時,先賦值0xFF
while(RD_sta() & 0x80);//bit7等于1表示忙,一直檢測到0為止
}
unsigned char RD_sta()//讀狀態(tài)函數(shù)
{
unsigned char sta;
RS_1602 = 0;
RW_1602 = 1;//進入讀1602狀態(tài)模式
EN_1602 = 1;//拉高使能信號
sta = P0; //將1602狀態(tài)數(shù)據(jù)讀取
EN_1602 = 0;//拉低使能,完成讀操作
return sta; //將狀態(tài)值返
}
void WR_Cmd(unsigned char cmd)//寫指令函數(shù)
{
Ready(); //檢測1602是否處于空閑狀態(tài)
RS_1602 = 0;
RW_1602 = 0;//進入寫指令模式
P0 = cmd; //將指令數(shù)據(jù)輸出
EN_1602 = 1;//拉高使能信號
EN_1602 = 0;//拉低使能,完成寫操作
}
void WR_Dat(unsigned char dat)//寫數(shù)據(jù)函數(shù)
{
Ready(); //檢測1602是否處于空閑狀態(tài)
RS_1602 = 1;
RW_1602 = 0;//進入寫數(shù)據(jù)模式
P0 = dat; //將數(shù)據(jù)輸出
EN_1602 = 1;//拉高使能信號
EN_1602 = 0;//拉低使能,完成寫操作
}
將上面程序下載到 RY-51 開發(fā)板后觀察現(xiàn)象,并通過調(diào)準(zhǔn)可變電阻 R6 觀察 1602 顯示器對比度的變化。
大家有沒有發(fā)現(xiàn),我們將和 1602 有關(guān)的函數(shù)都放在主程序所在的.c 文件中,以后我們每次要用到 1602 時,都要將這些函數(shù)復(fù)制到主函數(shù)下面,這樣是不是有點不方便。其實,我們可將這些函數(shù)都放到另外一個.c 文件、將函數(shù)聲明放到一個。h 格式的文件中,在主程序中我們只要包含這個文件就可以了,主程序代碼如下:
#include < reg52.h >
#include "Drive_1602.h"
sbit DU = P2^7;//數(shù)碼管段選、位選引腳定義
sbit WE = P2^6;
void main()
{
P0 = 0;//關(guān)閉所有數(shù)碼管
WE = 1;
WE = 0;
Init_1602();//1602初始化
Disp_1602_str(1,3,"RongYi RY-51");//第1行第3列開始顯示"RongYi RY-51"
while(1);
}
如上圖所示,將 Drive_1602.c、Drive_1602.h 添加到工程當(dāng)中,并且在主函數(shù)文件 Main1602.c 中添加語句#include "Drive_1602.h"即可。Drive_1602.h 文件內(nèi)容如下所示:
#ifndef __1602_H__
#define __1602_H__
//字符串顯示函數(shù)聲明
extern void Disp_1602_str(unsigned char row,unsigned char column,char *str);
extern void Init_1602();//1602初始化函數(shù)聲明
void Ready();//空閑檢測函數(shù)聲明
void WR_Cmd(unsigned char cmd);//寫指令函數(shù)聲明
void WR_Dat(unsigned char dat);//寫數(shù)據(jù)函數(shù)聲明
unsigned char RD_sta();//讀狀態(tài)函數(shù)聲明
#endif
關(guān)鍵字“extern”表示該函數(shù)可以在其它文件中被調(diào)用。Drive_1602.c 部分代碼如下所示:
#include < reg52.h >
#include "Drive_1602.h"
sbit RS_1602 = P3^4; //1602,RS、R/W,E引腳定義
sbit RW_1602 = P3^5;
sbit EN_1602 = P3^6;
//字符串顯示功能:從第row行,第column列開始顯示字符串str
void Disp_1602_str(unsigned char row,unsigned char column,char *str)
{
unsigned char addr;
addr = (row-1)*0x40 + (column-1);//組合成地址
WR_Cmd(0x80+addr);//寫地址命令
while(*str)//判斷str字符串是否已結(jié)束
{
WR_Dat(*str++);//將str字符串?dāng)?shù)據(jù)依次寫入
}
}
void Init_1602() //1602初始化函
{
WR_Cmd(0x38);//設(shè)置16x2顯示,5x7點陣,8位數(shù)據(jù)接口
WR_Cmd(0x0C);//開顯示,關(guān)閉光標(biāo)
WR_Cmd(0x06);//讀或?qū)懲暌粋€字符后,地址指針、光標(biāo)均加1
WR_Cmd(0x01);//數(shù)據(jù)指針清零、所示顯示清零
}
void Ready() //空閑檢測函數(shù)
{
P0 = 0xFF;//P0端口設(shè)置為輸入時,先賦值0xFF
while(RD_sta() & 0x80);//bit7等于1表示忙,一直檢測到0為止
}
unsigned char RD_sta()//讀狀態(tài)函數(shù)
{
unsigned char sta;
RS_1602 = 0;
RW_1602 = 1;//進入讀1602狀態(tài)模式
EN_1602 = 1;//拉高使能信號
sta = P0; //將1602狀態(tài)數(shù)據(jù)讀取
EN_1602 = 0;//拉低使能,完成讀操作
return sta; //將狀態(tài)值返
}
void WR_Cmd(unsigned char cmd)//寫指令函數(shù)
{
Ready(); //檢測1602是否處于空閑狀態(tài)
RS_1602 = 0;
RW_1602 = 0;//進入寫指令模式
P0 = cmd; //將指令數(shù)據(jù)輸出
EN_1602 = 1;//拉高使能信號
EN_1602 = 0;//拉低使能,完成寫操作
}
void WR_Dat(unsigned char dat)//寫數(shù)據(jù)函數(shù)
{
Ready(); //檢測1602是否處于空閑狀態(tài)
RS_1602 = 1;
RW_1602 = 0;//進入寫數(shù)據(jù)模式
P0 = dat; //將數(shù)據(jù)輸出
EN_1602 = 1;//拉高使能信號
EN_1602 = 0;//拉低使能,完成寫操作
}
除了如上面定義語句外,其他函數(shù)代碼均從最開始的主程序中拷貝過來即可。
11.6 本章小結(jié)
本章詳細(xì)介紹了1602字符顯示的原理,以及讀寫操作函數(shù)的實現(xiàn),后續(xù)項目中需要顯示字符時,調(diào)用上面的函數(shù)即可。
-
單片機
+關(guān)注
關(guān)注
6063文章
44915瀏覽量
646897 -
寄存器
+關(guān)注
關(guān)注
31文章
5421瀏覽量
123320 -
液晶顯示
+關(guān)注
關(guān)注
6文章
597瀏覽量
40763 -
顯示模塊
+關(guān)注
關(guān)注
1文章
53瀏覽量
23742
發(fā)布評論請先 登錄
使用1602液晶顯示的實驗例子
1602液晶顯示模塊的應(yīng)用

基于單片機的液晶屏1602-LCD液晶顯示【C語言+匯編】
使用51單片機實現(xiàn)LCD1602液晶顯示實驗的程序免費下載

51單片機怎么顯示當(dāng)前時間_(記錄)51單片機——LCD1602液晶顯示模塊

評論