51單片機(jī)編程開發(fā)(十)之液晶顯示

顯示屏
前面我們介紹數(shù)碼管時(shí)講到過(guò)顯示器在單片機(jī)應(yīng)用中是非常常見(jiàn)的,數(shù)碼管是最基礎(chǔ)的一種顯示器?,F(xiàn)在的人機(jī)交互場(chǎng)景中顯示器是比按鍵更常見(jiàn)的一種工具,因?yàn)閹в杏|摸屏的顯示器在很多地方都能取代按鍵。這一點(diǎn)通過(guò)對(duì)比現(xiàn)在的手機(jī)和十幾年的手機(jī)就可以看出來(lái)了。我們前面說(shuō)過(guò)當(dāng)我們使用少數(shù)幾個(gè)數(shù)碼管時(shí)是可以使用單片機(jī)IO口直接驅(qū)動(dòng)顯示的,但需要顯示眾多內(nèi)容時(shí)如果單純靠單片機(jī)驅(qū)動(dòng)就可能不合適了,一方面是占用太多IO口,造成單片機(jī)資源浪費(fèi),另一方面是,數(shù)碼管都是通過(guò)LED點(diǎn)亮的,比較耗能?;谶@些現(xiàn)實(shí)顯示驅(qū)動(dòng)應(yīng)運(yùn)而生,同時(shí)一些帶有顯示驅(qū)動(dòng)的單片機(jī)也隨著出現(xiàn),另外更多新型的顯示器也不斷出現(xiàn),又促成各種顯示驅(qū)動(dòng)芯片推陳出新。像GPU,顯卡這樣的高級(jí)模塊就是為復(fù)雜顯示而生,當(dāng)然這里面又涉及到顯示器的發(fā)展歷史,內(nèi)容過(guò)于豐富,就不細(xì)說(shuō),有興趣的朋友可以去了解一下。
今天我們要介紹的主角——LCD1602液晶屏,它是一種點(diǎn)陣液晶屏,與數(shù)碼管相比它能顯示更多內(nèi)容,也相對(duì)節(jié)能。當(dāng)然它是一種單色屏,相較于電視,電腦,手機(jī)等彩屏肯定就顯得單調(diào)了。并且在項(xiàng)目開發(fā)過(guò)程中我們用到LCD1602液晶屏的概率是微乎其微,但它又確實(shí)是入門學(xué)習(xí)不可缺少的一部分。萬(wàn)變不離其宗,我們能掌握使用它的方法后上手其他顯示屏就容易了。以后若做手機(jī),電腦等應(yīng)用端開發(fā)時(shí)都不用你接觸底層顯示原理,早有現(xiàn)成的驅(qū)動(dòng),也會(huì)有人負(fù)責(zé)UI,你直接調(diào)用就好了。當(dāng)然這是另外一碼事了,做單片機(jī)開發(fā)肯定還是會(huì)使用到各種屏幕的。另外工作的過(guò)程中你可能還會(huì)遇到一種液晶屏——段碼液晶屏,它更像是數(shù)碼管和液晶屏的結(jié)合體,因其在價(jià)格,能耗與制作工藝方面具備優(yōu)勢(shì),所以應(yīng)用非常廣泛,具體內(nèi)容我們以后再單獨(dú)做介紹。網(wǎng)絡(luò)上有各種屏幕的圖片,想提前了解的初學(xué)者可以自行搜索一下,我這里就暫不做過(guò)多說(shuō)明了。接下來(lái)我們先來(lái)了解一下LCD1602液晶屏的工作原理。
LCD液晶屏顯示原理
液晶(Liquid Crystal)是一種高分子材料,因?yàn)槠涮厥獾奈锢?、化學(xué)、光學(xué)特性,20世紀(jì)中葉開始廣泛應(yīng)用在輕薄型顯示器上。
液晶顯示器(Liquid Crystal Display,LCD)主要原理是以電流刺激液晶分子產(chǎn)生點(diǎn)、線、面并配合背部燈管構(gòu)成畫面。
現(xiàn)在來(lái)了解一下液晶的物理特性:LCD本身是不能發(fā)光的,它需要借助光源進(jìn)行顯示,即我們平時(shí)所說(shuō)的背光。當(dāng)光束通過(guò)這層液晶時(shí),液晶本身會(huì)排排站立或扭轉(zhuǎn)呈不規(guī)則狀,因而阻隔或使光束順利通過(guò)。
大多數(shù)液晶都屬于有機(jī)復(fù)合物,由長(zhǎng)棒狀的分子構(gòu)成。在自然狀態(tài)下,這些棒狀分子的長(zhǎng)軸大致平行。將液晶倒入一個(gè)經(jīng)精良加工的開槽平面,液晶分子會(huì)順著槽排列,所以假如那些槽非常平行,則各分子也是完全平行的。

也就是說(shuō),若一個(gè)平面上的分子南北向排列,則另一平面上的分子?xùn)|西向排列,而位于兩個(gè)平面之間的分子被強(qiáng)迫進(jìn)入一種90度扭轉(zhuǎn)的狀態(tài)。由于光線順著分子的排列方向傳播,所以光線經(jīng)過(guò)液晶時(shí)也被扭轉(zhuǎn)90度。但當(dāng)液晶上加一個(gè)電壓時(shí),分子便會(huì)重新垂直排列,使光線能直射出去,而不發(fā)生任何扭轉(zhuǎn)。
極化濾光器實(shí)際是一系列越來(lái)越細(xì)的平行線。這些線形成一張網(wǎng),阻斷不與這些線平行的所有光線。極化濾光器的線正好與第一個(gè)垂直,所以能完全阻斷那些已經(jīng)極化的光線。只有兩個(gè)濾光器的線完全平行,或者光線本身已扭轉(zhuǎn)到與第二個(gè)極化濾光器相匹配,光線才得以穿透。
所以通過(guò)這些特定方向的偏光片再施加電壓就可以讓部分區(qū)域光通過(guò),另外部分區(qū)域光遮擋,這些明暗相間的點(diǎn)按照一定的像素排列起來(lái)的圖像就是我們想要顯示的信息了。

1602液晶顯示模塊內(nèi)部包含驅(qū)動(dòng)芯片為HD44780(HITACHI)或其他兼容芯片,內(nèi)部提供了192種字符的庫(kù),用戶可以直接調(diào)用。它可以顯示兩行字符,每行包括16個(gè)5×8點(diǎn)陣塊組成的顯示字符塊,每個(gè)點(diǎn)陣塊為一個(gè)字符位,字符間距和行距都為一個(gè)點(diǎn)的寬度。
LCD1602顯示控制
了解LCD顯示原理之后,那要怎樣才能讓它顯示字符呢?這就要先了解其內(nèi)部驅(qū)動(dòng)芯片的特點(diǎn)和控制方式。單片機(jī)控制顯示器驅(qū)動(dòng)也是需要進(jìn)行通信的,這里就又涉及到我們之前一直強(qiáng)調(diào)的時(shí)序了,上一節(jié)講解uart時(shí)我們知道uart通信是要有嚴(yán)格的時(shí)序要求的,所以它才需要精準(zhǔn)的波特率來(lái)控制,液晶顯示器控制時(shí)序雖然不用像uart那樣精準(zhǔn),但也需要一定的要求。我們先來(lái)看一下它的常用接口和引腳說(shuō)明。

●VSS:電源地引腳。
●VDD:供電電源引腳。
●Vo:液晶顯示偏壓信號(hào)引腳,外加0 ~5V電壓以調(diào)節(jié)顯示對(duì)比度。
●RS:寄存器選擇引腳,為高電平時(shí)選擇數(shù)據(jù)寄存器;為低電平時(shí)選擇指令寄存器。
●R/W:讀、寫操作選擇引腳,高電平時(shí)為讀操作;低電平時(shí)為寫操作。
●E:使能信號(hào)引腳,低電平有效。
●DB0 ~ DB7:數(shù)據(jù)總線引腳,用于輸入驅(qū)動(dòng)1602液晶模塊顯示的數(shù)據(jù)。
●A:背光5V電源引腳。
●K:背光地信號(hào)引腳。
現(xiàn)在我們?cè)賮?lái)了解它的控制時(shí)序:

從圖中可以看出,它的讀寫操作中RS,R/W,E三個(gè)控制引腳的時(shí)序變化是不一樣的。并且數(shù)據(jù)與指令也有區(qū)別,這樣就具體可以分為一下4種情況:
讀狀態(tài)——輸入:RS=L,R/W=H,E=H;輸出:D0~D7=狀態(tài)字。
讀數(shù)據(jù)——輸入:RS=H,R/W=H,E=H;輸出:無(wú)。
寫指令——輸入:RS=L,R/W=L,E=H,D0~D7=指令碼,E=H;輸出:D0~D7=數(shù)據(jù)。
寫數(shù)據(jù)——輸入:RS=H,R/W=L,E=H,D0~D7=數(shù)據(jù),E=H;輸出:無(wú)。
顯示器內(nèi)部驅(qū)動(dòng)芯片帶有80字節(jié)的RAM緩沖區(qū),其地址對(duì)應(yīng)如下:

但是我們知道顯示屏界面做多只能顯示16*2個(gè)字符,那它內(nèi)部要怎么處理所有的緩沖區(qū)呢?
向圖中的00H~0FH、40H~4FH地址中的任意處寫顯示數(shù)據(jù)時(shí),液晶都可以立即顯示出來(lái);但寫入到10H~27H或50H~67H地址處時(shí),必須通過(guò)移屏指令將他們移入可顯示區(qū)域才能正常顯示。
顯示器內(nèi)部?jī)?nèi)置字符串分布表如下:

顯示驅(qū)動(dòng)的控制指令如下:

以上內(nèi)容比較多,并且還有部分信息沒(méi)有完全列出,這里也不一一列出了,使用時(shí)不用記憶,只需對(duì)照資料進(jìn)行編程就好。
LCD1602顯示示例
以上介紹了1602液晶顯示器相關(guān)的主要內(nèi)容,現(xiàn)在我們繪制一個(gè)簡(jiǎn)單的電路圖再編程測(cè)試一下。

什么的電路中我們將顯示器數(shù)據(jù)端口連接在P0上,其他3根控制引腳連接在P2.2~P2.4上。
現(xiàn)在我們編程讓它來(lái)顯示一些簡(jiǎn)單的字符:
/*
*這是一個(gè)LCD1602顯示程序
*目的是通過(guò)顯示屏顯示一些字符
*/
#include <reg52.h>
#include <intrins.h>
#define DB1602 P0 ? ? ? ? ? ?//1602數(shù)據(jù)口
typedef unsigned char u8;
typedef unsigned int ?u16;
sbit rs_1602=P2^2;
sbit rw_1602=P2^3;
sbit en_1602=P2^4;
void delay(u8 ms);
void lcd1602_check_busy();
void Write_Byte_1602(u8 Byte,bit dat);
void lcd1602_Init();
void Write_char1_1602(bit x,u8 y,u8 dat1);
void Write_string_1602(bit x,u8 y,u8 *str);
void main(void)
{
lcd1602_Init();
Write_string_1602(0,0," ?Hello guy!");
Write_char1_1602(1,6,'-');
Write_string_1602(1,7,"--LCD1602");
while(1)
{
}
}
void delay(u8 ms)
{
? ? u8 i,j;
? ? for(i=0; i<ms; i++)
? ? {
? ? ? ? for(j=0; j<110; j++)
? ? ? ? {
? ? ? ? ? ? ;
? ? ? ? }
? ? }
}
void lcd1602_check_busy()
{
? u8 busy;
? bit via;
? do
? {
? ? ?rs_1602=0;
?rw_1602=1;
?DB1602|=0xf0;
?en_1602=1;
?busy=DB1602;
?en_1602=0;
?en_1602=1; ??//
?en_1602=0; ??//
?via=(bit)(busy&0x80);
? }while(via);
}
void Write_Byte_1602(u8 Byte,bit dat)
{
?lcd1602_check_busy(); //忙則等待
?rs_1602=dat; ?//數(shù)據(jù)命令選擇位
?rw_1602=0;
?en_1602=1;
?DB1602=Byte;
?_nop_();
? ? ?en_1602=0;
}
void lcd1602_Init()
{ ?
?Write_Byte_1602(0x38,0); ??//設(shè)置16×2顯示,5×7點(diǎn)陣,8位數(shù)據(jù)接口
?Write_Byte_1602(0x08,0); ??
?Write_Byte_1602(0x01,0); ??//顯示清屏
?Write_Byte_1602(0x06,0); ??//顯示光標(biāo)移動(dòng)設(shè)置
?Write_Byte_1602(0x0c,0); ??//顯示開及光標(biāo)設(shè)置
}
void Write_char1_1602(bit x,u8 y,u8 dat1)
{
?if(x==0)
?{
Write_Byte_1602(0x80+y,0);
?}
?else
?{
? Write_Byte_1602(0xc0+y,0);
?}
?//dat1+=0x30;
?Write_Byte_1602(dat1,1);
}
void Write_string_1602(bit x,u8 y,u8 *str)
{
?if(x==0)
?{
Write_Byte_1602(0x80+y,0);
?}
?else
?{
? Write_Byte_1602(0xc0+y,0);
?}
?while(*str)
?{
? ?Write_Byte_1602(*str,1);
?str++;
?}
}
這段代碼看起來(lái)比原來(lái)的程序都復(fù)雜一點(diǎn),但還是一些比較基礎(chǔ)的內(nèi)容,所以大家先自己理解一下,不理解地方可以先看一下資料,這段程序中使用到了我之前沒(méi)提到過(guò)的內(nèi)容——指針,后面我會(huì)單獨(dú)列出出來(lái)進(jìn)行講解。

結(jié)語(yǔ):
今天這篇文章我們將1602顯示器的使用做了一個(gè)簡(jiǎn)單的講解,51單片機(jī)的基礎(chǔ)應(yīng)用部分知識(shí)就介紹完了,后面我們?cè)俳榻B一些其他擴(kuò)展功能。如果需要程序源碼或仿真電路圖文件的朋友可以私信,我將會(huì)整理一份資料包進(jìn)行共享。