1.初識 LCD1602
LCD ( Liquid Crystal Display 的簡稱)液晶顯示器。
LCD 的構(gòu)造是在兩片平行的玻璃基板當(dāng)中放置液晶盒,下基板玻璃上設(shè)置TFT(薄膜晶體管),上基板玻璃上設(shè)置彩色濾光片,通過TFT上的信號與電壓改變來控制液晶分子的轉(zhuǎn)動方向,從而達(dá)到控制每個像素點偏振光出射與否而達(dá)到顯示目的。
1.1.1602 液晶的硬件接口
1602 液晶,從它的名字我們就可以看出它的顯示容量,就是可以顯示 2 行,每行 16 個字符的液晶。它的工作電壓為 4.5V~5.5V ,對于這點我們在設(shè)計電路的時候,直接按照 5V 系統(tǒng)設(shè)計即可,但是要保證我們的 5V 系統(tǒng)不能低于 4.5V 。在 5V 工作電壓下測量它的工作電流是 2mA ,大家注意,這個 2mA 僅僅是指液晶,而它的黃綠背光都是用 LED 做的,所以功耗不會太小。
1602 液晶一共有 16 個引腳,每個引腳的功能,我們都可以在它的數(shù)據(jù)手冊中獲取。而這些基本信息,在我們設(shè)計電路和編寫程序之前,必須先看明白。
液晶的電源 1 腳 2 腳以及背光電源的 15 腳 16 腳,不用多說,正常接就可以了。
3 腳叫做液晶顯示偏壓信號,大家注意到小黑塊沒有,當(dāng)我們要顯示一個字符的時候,有的黑點顯示,有的黑點就不能顯示,這樣就可以實現(xiàn)我們想要的字符了。我們這個 3 腳就是用來調(diào)整顯示的黑點和不顯示的之間的對比度,調(diào)整好了對比度,就可以讓我們的顯示更加清晰一些。在進(jìn)行電路設(shè)計實驗的時候,通常的辦法是在這個引腳上接個電位器,也就是我們初中學(xué)過的滑動變阻器。通過調(diào)整電位器的分壓值,來調(diào)整 3 腳的電壓。而當(dāng)產(chǎn)品批量生產(chǎn)的時候,我們可以把我們調(diào)整好的這個值直接用簡單電路來實現(xiàn)。
4 腳是數(shù)據(jù)命令選擇端。對于液晶,有時候我們要發(fā)送一些命令,讓它實現(xiàn)我們想要的一些狀態(tài),有時候我們要發(fā)給它一些數(shù)據(jù),讓它顯示出來,液晶就通過這個引腳來判斷接收到的是命令還是數(shù)據(jù)。大家注意學(xué)會讀手冊,看到這個引腳描述里:數(shù)據(jù)/命令選擇端,而后跟了括號(H/L),他的意思就是當(dāng)這個引腳是 H(High)高電平的時候,是數(shù)據(jù),當(dāng)這個引腳是 L(Low)低電平的時候,是命令。
5 腳和 4 腳用法類似,功能是讀寫選擇端。我們既可以寫給液晶數(shù)據(jù)或者命令,也可以讀取液晶內(nèi)部的數(shù)據(jù)或狀態(tài),就是控制這個引腳。因為液晶本身內(nèi)部有 RAM,實際上我們送給液晶的命令或者數(shù)據(jù),液晶需要先保存在緩存里,然后再寫到內(nèi)部的寄存器或者 RAM中,這個就需要一定的時間。所以我們進(jìn)行讀寫操作之前,首先要讀一下液晶當(dāng)前狀態(tài),是不是在“忙”,如果不忙,我們可以讀寫數(shù)據(jù),如果在“忙”,我們就需要等待液晶忙完了,再進(jìn)行操作。讀狀態(tài)是常用的,不過讀液晶數(shù)據(jù)我接觸的場合沒怎么用過,大家了解這個功能即可。
6 腳是使能信號,很關(guān)鍵,液晶的讀寫命令和數(shù)據(jù),都要靠它才能正常讀寫,我們后邊詳細(xì)講這個引腳怎么用。
7 到 14 引腳就是 8 個數(shù)據(jù)引腳了,我們就是通過這 8 個引腳讀寫數(shù)據(jù)和命令的,統(tǒng)一接到了 P0 口上。
1.2.1602 液晶的讀寫時序
1602 的時序問題,大家要學(xué)會通過 LCD1602 的數(shù)據(jù)手冊提供的時序圖和時序參數(shù)表格來進(jìn)行研究,而且看懂時序圖是學(xué)習(xí)單片機(jī)所必須掌握的一項技能,如下圖:
我們先來看一下讀操作時序的 RS 引腳和 R/W 引腳,這兩個引腳先進(jìn)行變化,因為是讀操作,所以 R/W 引腳首先要置為高電平,而不管它原來是什么。讀指令還是讀數(shù)據(jù),都是讀操作,而且都有可能,所以 RS 引腳既有可能是置為高電平,也有可能是置為低電平,大家注意圖上的畫法。而 RS 和 R/W 變化了經(jīng)過 Tsp1 這么長時間后,使能引腳 E 才能從低電平到高電平發(fā)生變化。
而使能引腳 E 拉高經(jīng)過了 tD 這么長時間后,LCD1602 輸出 DB 的數(shù)據(jù)就是有效數(shù)據(jù)了,我們就可以來讀取 DB 的數(shù)據(jù)了。讀完了之后,我們要先把使能 E 拉低,經(jīng)過一段時間后 RS、R/W 和 DB 才可以變化繼續(xù)為下一次讀寫做準(zhǔn)備了。
而寫操作時序和讀操作時序的差別,就是寫操作時序中,DB 的改變是由單片機(jī)來完成的,因此要放到使能引腳 E 的變化之前進(jìn)行操作,其它區(qū)別大家可以自行對比一下。
細(xì)心的同學(xué)會發(fā)現(xiàn),這個時序圖上還有很多時間標(biāo)簽。比如 E 的上升時間 tR,下降時間時間 tF,使能引腳 E 從一個上升沿到下一個上升沿之間的長度周期 tC,使能 E 下降沿后,R/W 和 RS 變化時間間隔 tHD1 等等很多時間要求,這些要求怎么看呢?放心,只要是正規(guī)的數(shù)據(jù)手冊,都會把這些時間要求給大家標(biāo)記出來的。我們來看下表 :
tC:指的是使能引腳 E 從本次上升沿到下次上升沿的最短時間是 400ns,而我們單片機(jī)因為速度較慢,一個機(jī)器周期就是 1us 多,而一條 C 語言指令肯定是一個或者幾個機(jī)器周期的,所以這個條件完全滿足。
tPW:指的是使能引腳 E 高電平的持續(xù)時間最短是 150ns,同樣由于我們的單片機(jī)比較慢,這個條件也完全滿足。
tR, tF:指的是使能引腳 E 的上升沿時間和下降沿時間,不能超過 25ns,別看這個數(shù)很小,其實這個時間限值是很寬裕的,我們實際用示波器測了一下開發(fā)板的這個引腳上升沿和下降沿時間大概是 10ns 到 15ns 之間,完全滿足。
tSP1:指的是 RS 和 R/W 引腳使能后至少保持 30ns,使能引腳 E 才可以變成高電平,這個條件同樣也完全滿足。
tHD1:指的是使能引腳 E 變成低電平后,至少保持 10ns 之后,RS 和 R/W 才能進(jìn)行變化,這個條件也完全滿足。
tD:指的是使能引腳 E 變成高電平后,最多 100ns 后,1602 就把數(shù)據(jù)送出來了,那么我們就可以正常去讀取狀態(tài)或者數(shù)據(jù)了。
tHD2:指的是讀操作過程中,使能引腳 E 變成低電平后,至少保持 20ns,DB 數(shù)據(jù)總線才可以進(jìn)行變化,這個條件也完全滿足。
tSP2:指的是 DB 數(shù)據(jù)總線準(zhǔn)備好后,至少保持 40ns,使能引腳 E 才可以從低到高進(jìn)行使能變化,這個條件也完全滿足。
tHD2:指的是寫操作過程中,要引腳 E 變成低電平后,至少保持 10ns,DB 數(shù)據(jù)總線才可以變化,這個條件也完全滿足。
1602 液晶內(nèi)部帶了 80 個字節(jié)的顯示 RAM ,用來存儲我們發(fā)送的數(shù)據(jù),它的構(gòu)造如圖所示:
第一行的地址是 0x00H 到 0x27,第二行的地址從 0x40 到 0x67,其中第一行 0x00 到 0x0F 是與液晶上第一行 16 個字符顯示位置相對應(yīng)的,第二行 0x40 到 0x4F 是與第二行 16 個字符顯示位置相對應(yīng)的。而每行都多出來一部分,是為了顯示移動字幕設(shè)置的。1602 字符液晶是顯示字符的,因此它跟 ASCII 字符表是對應(yīng)的。比如我們給 0x00 這個地址寫一個‘a(chǎn)’,也就是十進(jìn)制的 97,液晶的最左上方的那個小塊就會顯示一個字母 a。
液晶有一個狀態(tài)字字節(jié),我們通過讀取這個狀態(tài)字的內(nèi)容,就可以知道 1602 液晶的一些內(nèi)部情況,如下表所示。
這個狀態(tài)字節(jié)有 8 個位,最高位表示了當(dāng)前液晶是不是“忙”,如果這個位是 1 表示液晶正“忙”,禁止我們讀寫數(shù)據(jù)或者命令,如果是 0,則可以進(jìn)行讀寫。而低 7 位就表示了當(dāng)前數(shù)據(jù)地址指針的位置。
1602 的基本操作時序,一共有 4 個,這些大家都不需要記住,但是都需要理解,因為我們現(xiàn)在不是為了應(yīng)付考試,所以不需要你把手冊背熟,但是你寫程序的時候,打開手冊要能看懂如何操作,還要再提醒一句,單片機(jī)讀外部狀態(tài)前,必須先保證自己是高電平哦。
我們這里要做 1602 液晶的程序,因此先把用到的總線接口做一個統(tǒng)一聲明:
#define LCD1602_DB P0
sbit LCD1602_RS = P2^6 ;
sbit LCD1602_RW = P2^5 ;
sbit LCD1602_E = P2^7 ;
1、讀狀態(tài):RS = L , R/W = H ,E = H 。這個邏輯很簡單,也就是說我們接著寫:
LCD1602_DB = 0xFF ;
LCD1602_RS = 0 ;
LCD1602_RW = 1 ;
LCD1602_E = 1 ;
sta = LCD1602_DB ;
這樣就把當(dāng)前液晶的狀態(tài)字讀到了 sta 這個變量中,我們可以通過判斷 sta 最高位的值來了解當(dāng)前液晶是否處于“忙”狀態(tài),也可以得知當(dāng)前數(shù)據(jù)的指針位置。兩個問題,一是如果我們當(dāng)前讀到的狀態(tài)是“不忙”,那么我們程序可以進(jìn)行讀寫操作,如果當(dāng)前狀態(tài)是“忙”,那么我們還得繼續(xù)等待重新判斷液晶的狀態(tài);問題二,大家可以看我之前的文章,流水燈、數(shù)碼管、點陣、1602 液晶都是用到了 P0 口總線,我們讀完了液晶狀態(tài)繼續(xù)保持 LCD1602_E 是高電平的話,1602 液晶會繼續(xù)輸出它的狀態(tài)值,輸出的這個值會占據(jù)了 P0 總線,干擾到流水燈數(shù)碼管等其它外設(shè),所以我們讀完了狀態(tài),通常要把這個引腳拉低來釋放總線,這里我們用了一個 do…while 循環(huán)語句來實現(xiàn)。
uchar sta ;
LCD1602_DB = 0xFF ;
LCD1602_RS = 0 ;
LCD1602_RW = 1 ;
do
{
LCD1602_E = 1 ;
sta = LCD1602_DB ; // 讀取狀態(tài)字
LCD1602_E = 0 ;
} while(sta & 0x80) ; // bit7為1表示液晶正忙,重復(fù)檢測為0為止
2、讀數(shù)據(jù):RS=H,R/W=H,E=H。這個邏輯也很簡單,但是讀數(shù)據(jù)不常用,大家了解一下就可以了,這里就不詳細(xì)解釋了。
3、寫指令:RS=L,R/W=L,D0~D7=指令碼,E=高脈沖。
這個在邏輯上沒什么難的,只是 E=高脈沖這個問題要解釋一下。這個指令一共有 4 條語句,其中前三條語句順序無所謂,但是 E=高脈沖這一句很關(guān)鍵。實際上流程是這樣的:因為我們現(xiàn)在是寫數(shù)據(jù),所以我們首先要保證我們的 E 引腳是低電平狀態(tài),而前三句不管我們怎么寫,1602 液晶只要沒有接收到 E 引腳的使能控制,它都不會來讀總線上的信號的。當(dāng)通過前三句準(zhǔn)備好數(shù)據(jù)之后,E 使能引腳從低電平到高電平變化,然后 E 使能引腳再從高電平到低電平出現(xiàn)一個下降沿,1602 液晶內(nèi)部一旦檢測到這個下降沿后,并且檢測到 RS=L,R/W=L,就馬上來讀取 D0~D7 的數(shù)據(jù),完成單片機(jī)寫 1602 指令過程。歸納總結(jié)我們寫了個 E=高脈沖,意思就是:E 使能引腳先從低拉高,再從高拉低,形成一個高脈沖。
4、寫數(shù)據(jù):RS=H,R/W=L,D0~D7=數(shù)據(jù),E=高脈沖。
寫數(shù)據(jù)和寫指令是類似的,就是把 RS 改成 H,把總線改成數(shù)據(jù)即可。
此外要順便提一句,這里用的1602液晶所使用的接口時序是摩托羅拉公司所創(chuàng)立的 6800時序,還有另外一種時序是 Intel 公司的 8080 時序,也有部分液晶模塊采用,只是相對來說比較少見,大家知道這么回事即可。
1.3.1602 液晶的指令
與單片機(jī)寄存器的用法類似,1602 液晶在使用的時候,我們首先要進(jìn)行初始的功能配置,1602 液晶有以下幾個指令需要了解。
1、顯示模式設(shè)置。
寫指令 0x38,設(shè)置 16x2 顯示,5x7 點陣,8 位數(shù)據(jù)接口。這條指令對我們這個液晶來說是固定的,必須寫 0x38,大家仔細(xì)看會發(fā)現(xiàn)我們的液晶實際上內(nèi)部點陣是 5x8 的,還有一些 1602 液晶還兼容串行通信,用 2 個 IO 口即可,但是速度慢,我們這個液晶就是固定的 0x38 模式。
2、顯示開/關(guān)以及光標(biāo)設(shè)置指令。
這里有 2 條指令,第一條指令,一個字節(jié)中 8 位,其中高 5 位是固定的 0b00001,低 3 位我們分別用 DCB 從高到低表示,D=1 表示開顯示,D=0 表示關(guān)顯示;C=1 表示顯示光標(biāo),C=0 表示不顯示光標(biāo);B=1 表示光標(biāo)閃爍,B=0 表示光標(biāo)不閃爍。
第二條指令,高 6 位是固定的 0b000001,低 2 位我們分別用 NS 從高到低表示,其中 N=1 表示讀或者寫一個字符后,指針自動加 1,光標(biāo)自動加 1,N=0 表示讀或者寫一個字符后指針自動減 1,光標(biāo)自動減 1;S=1 表示寫一個字符后,整屏顯示左移(N=1)或右移(N=0),以達(dá)到光標(biāo)不移動而屏幕移動的效果,如同我們的計算器輸入一樣的效果,而 S=0 表示寫一個字符后,整屏顯示不移動。
3、清屏指令。
固定的,寫入 0x01 表示顯示清屏,其中包含了數(shù)據(jù)指針清零,所有的顯示清零。寫入 0x02 則僅僅是數(shù)據(jù)指針清零,顯示不清零。
4、RAM 地址設(shè)置指令。
該指令碼的最高位為 1,低 7 位為 RAM 的地址,RAM 地址與液晶上字符的關(guān)系如上表所示。通常,我們在讀寫數(shù)據(jù)之前都要先設(shè)置好地址,然后再進(jìn)行數(shù)據(jù)的讀寫操作。
2.實例
2.1.顯示字符
1602 液晶手冊提供了一個初始化過程,由于不檢測“忙”位,所以程序比較復(fù)雜,而我們總結(jié)了一個更加簡易方便的過程提供給大家,手冊上描述的那個,大家僅僅作為了解就可以了,下面我把程序?qū)懗鰜泶蠹铱聪?,我們的初始化只用?4 條語句,沒有像手冊介紹的那么繁瑣。
#include<reg52.h>
typedef unsigned char uchar ;
typedef unsigned int uint ;
typedef unsigned long ulong ;
#define LCD1602_DB P0
sbit LCD1602_RS = P2^6 ;
sbit LCD1602_RW = P2^5 ;
sbit LCD1602_E = P2^7 ;
void InitLcd1602();
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void main()
{
unsigned char str[] = "Kingst Studio";
InitLcd1602();
LcdShowStr(2, 0, str);
LcdShowStr(0, 1, "Welcome to YU");
while (1);
}
/* 液晶等待函數(shù) */
void LcdWaitReady()
{
uchar sta ;
LCD1602_DB = 0xFF ;
LCD1602_RS = 0 ;
LCD1602_RW = 1 ;
do
{
LCD1602_E = 1 ;
sta = LCD1602_DB ; // 讀取狀態(tài)字
LCD1602_E = 0 ;
} while(sta & 0x80) ; // bit7為1表示液晶正忙,重復(fù)檢測為0為止
}
/* 向LCD1602寫入命令函數(shù) */
void LcdWriteCmd(uchar cmd)
{
LcdWaitReady() ;
LCD1602_RS = 0 ;
LCD1602_RW = 0 ;
LCD1602_DB = cmd ;
LCD1602_E = 1 ;
LCD1602_E = 0 ;
}
/* 向LCD1602寫入數(shù)據(jù)函數(shù) */
void LcdWriteDat(uchar dat)
{
LcdWaitReady() ;
LCD1602_RS = 1 ;
LCD1602_RW = 0 ;
LCD1602_DB = dat ;
LCD1602_E = 1 ;
LCD1602_E = 0 ;
}
/* 設(shè)置RAM起始地址,亦光標(biāo)位置,(x,y)- 對應(yīng)屏幕上的字符坐標(biāo) */
void LcdSetCursor(uchar x , uchar y)
{
uchar addr ;
if (y == 0) // 由輸入的屏幕坐標(biāo)計算顯示RAM的地址
addr = 0x00 + x ;
else
addr = 0x40 + x ;
LcdWriteCmd(addr | 0x80) ; // 設(shè)置RAM的地址
}
/* 在液晶上顯示字符串 (x,y)- 對應(yīng)屏幕上的起始坐標(biāo),stc - 字符串指針 */
void LcdShowStr(uchar x , uchar y ,uchar *str)
{
LcdSetCursor(x , y) ; // 設(shè)置起始地址
while(*str != '\0')
{
LcdWriteDat(*str ++) ; // 連續(xù)寫入字符串?dāng)?shù)據(jù),直到檢測到結(jié)束符
}
}
/* 區(qū)域清除,清除從(x,y)坐標(biāo)起始的len個字符位 */
void LcdAreaClear(uchar x , uchar y , uchar len)
{
LcdSetCursor(x , y) ;
while(len --)
{
LcdWriteDat(' ') ;
}
}
/* 整屏清除 */
void LcdFullClear()
{
LcdWriteCmd(0x01) ;
}
/* LCD1602初始化 */
void InitLcd1602()
{
LcdWriteCmd(0x38) ; // 16*2 顯示,5*7點陣,8位數(shù)據(jù)接口
LcdWriteCmd(0x0C) ; // 顯示器開,光標(biāo)關(guān)閉
LcdWriteCmd(0x06) ; // 文字不動,地址自動+1
LcdWriteCmd(0x01) ; // 清屏
}
文章來源:http://www.zghlxwxcb.cn/news/detail-489206.html
2.2.整屏移動
我們前邊學(xué)點陣 LED 的時候,可以實現(xiàn)上下移動,左右移動等。而對于 1602 液晶來說,也可以進(jìn)行屏幕移動,實現(xiàn)我們想要的一些效果,那我們來用一個例程實現(xiàn)字符串在 1602 液晶上的左移。文章來源地址http://www.zghlxwxcb.cn/news/detail-489206.html
#include<reg52.h>
typedef unsigned char uchar ;
typedef unsigned int uint ;
typedef unsigned long ulong ;
#define LCD1602_DB P0
sbit LCD1602_RS = P2^6 ;
sbit LCD1602_RW = P2^5 ;
sbit LCD1602_E = P2^7 ;
bit flag500ms = 0; //500ms 定時標(biāo)志
uchar T0RH = 0; //T0 重載值的高字節(jié)
uchar T0RL = 0; //T0 重載值的低字節(jié)
//待顯示的第一行字符串
uchar code str1[] = "Kingst Studio";
//待顯示的第二行字符串,需保持與第一行字符串等長,較短的行可用空格補(bǔ)齊
uchar code str2[] = "Let's move...";
void ConfigTimer0(uint ms);
void InitLcd1602();
void LcdShowStr(uchar x, uchar y, uchar *str, uchar len);
void main()
{
uchar i;
uchar index = 0; //移動索引
uchar pdata bufMove1[16+sizeof(str1)+16]; //移動顯示緩沖區(qū) 1
uchar pdata bufMove2[16+sizeof(str2)+16]; //移動顯示緩沖區(qū) 2
EA = 1; //開總中斷
ConfigTimer0(10); //配置 T0 定時 10ms
InitLcd1602(); //初始化液晶
//緩沖區(qū)開頭一段填充為空格
for (i=0; i<16; i++)
{
bufMove1[i] = ' ';
bufMove2[i] = ' ';
}
//待顯示字符串拷貝到緩沖區(qū)中間位置
for (i=0; i<(sizeof(str1)-1); i++)
{
bufMove1[16+i] = str1[i];
bufMove2[16+i] = str2[i];
}
//緩沖區(qū)結(jié)尾一段也填充為空格
for (i=(16+sizeof(str1)-1); i<sizeof(bufMove1); i++)
{
bufMove1[i] = ' ';
bufMove2[i] = ' ';
}
while (1)
{
if (flag500ms) //每 500ms 移動一次屏幕
{
flag500ms = 0;
//從緩沖區(qū)抽出需顯示的一段字符顯示到液晶上
LcdShowStr(0, 0, bufMove1+index, 16);
LcdShowStr(0, 1, bufMove2+index, 16);
//移動索引遞增,實現(xiàn)左移
index++;
if (index >= (16+sizeof(str1)-1))
{ //起始位置達(dá)到字符串尾部后即返回從頭開始
index = 0;
}
}
}
}
/* 定時器函數(shù) */
void ConfigTimer0(uint ms)
{
ulong tmp ;
tmp = 11059200 / 12 ; // 定時器頻率
tmp = (tmp * ms) / 1000 ; // 計算所需的計數(shù)值
tmp = 65536 - tmp ; // 計算定時器重載值
tmp = tmp + 18 ; // 補(bǔ)償中斷響應(yīng)延時造成的誤差
T0RH = (uchar)(tmp >> 8) ;
T0RL = (uchar)tmp ;
TMOD = TMOD & 0xF0 ;
TMOD = TMOD | 0x01 ;
TH0 = T0RH ; // 加載T0重載值
TL0 = T0RL ;
ET0 = 1 ; // 使能T0中斷
TR0 = 1 ; // 啟動T0
}
/* 液晶等待函數(shù) */
void LcdWaitReady()
{
uchar sta ;
LCD1602_DB = 0xFF ;
LCD1602_RS = 0 ;
LCD1602_RW = 1 ;
do
{
LCD1602_E = 1 ;
sta = LCD1602_DB ; // 讀取狀態(tài)字
LCD1602_E = 0 ;
} while(sta & 0x80) ; // bit7為1表示液晶正忙,重復(fù)檢測為0為止
}
/* 向LCD1602寫入命令函數(shù) */
void LcdWriteCmd(uchar cmd)
{
LcdWaitReady() ;
LCD1602_RS = 0 ;
LCD1602_RW = 0 ;
LCD1602_DB = cmd ;
LCD1602_E = 1 ;
LCD1602_E = 0 ;
}
/* 向LCD1602寫入數(shù)據(jù)函數(shù) */
void LcdWriteDat(uchar dat)
{
LcdWaitReady() ;
LCD1602_RS = 1 ;
LCD1602_RW = 0 ;
LCD1602_DB = dat ;
LCD1602_E = 1 ;
LCD1602_E = 0 ;
}
/* 設(shè)置RAM起始地址,亦光標(biāo)位置,(x,y)- 對應(yīng)屏幕上的字符坐標(biāo) */
void LcdSetCursor(uchar x , uchar y)
{
uchar addr ;
if (y == 0) // 由輸入的屏幕坐標(biāo)計算顯示RAM的地址
addr = 0x00 + x ;
else
addr = 0x40 + x ;
LcdWriteCmd(addr | 0x80) ; // 設(shè)置RAM的地址
}
/* 在液晶上顯示字符串 (x,y)- 對應(yīng)屏幕上的起始坐標(biāo),stc - 字符串指針 */
void LcdShowStr(uchar x , uchar y ,uchar *str,uchar len)
{
LcdSetCursor(x , y) ; // 設(shè)置起始地址
while(len--)
{
LcdWriteDat(*str ++) ; // 連續(xù)寫入字符串?dāng)?shù)據(jù),直到檢測到結(jié)束符
}
}
/* 區(qū)域清除,清除從(x,y)坐標(biāo)起始的len個字符位 */
void LcdAreaClear(uchar x , uchar y , uchar len)
{
LcdSetCursor(x , y) ;
while(len --)
{
LcdWriteDat(' ') ;
}
}
/* 整屏清除 */
void LcdFullClear()
{
LcdWriteCmd(0x01) ;
}
/* LCD1602初始化 */
void InitLcd1602()
{
LcdWriteCmd(0x38) ; // 16*2 顯示,5*7點陣,8位數(shù)據(jù)接口
LcdWriteCmd(0x0C) ; // 顯示器開,光標(biāo)關(guān)閉
LcdWriteCmd(0x06) ; // 文字不動,地址自動+1
LcdWriteCmd(0x01) ; // 清屏
}
/* T0 中斷服務(wù)函數(shù),定時 500ms */
void InterruptTimer0() interrupt 1
{
static unsigned char tmr500ms = 0;
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
tmr500ms++;
if (tmr500ms >= 50)
{
tmr500ms = 0;
flag500ms = 1;
}
}
到了這里,關(guān)于51單片機(jī)入門——LCD1602的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!