LCD1602 液晶显示实验
LCD1602 簡(jiǎn)介
? ? ? ? ? ?LCD1602是一種用來(lái)顯示字母、數(shù)字、符號(hào)的點(diǎn)陣型液晶模塊,可顯示 2 行字符信息,每行又能顯示 16 個(gè)字符,每個(gè)字符由若干個(gè)( 5x7 或?5x10) 的點(diǎn)陣字符位組成, 每位之間有一個(gè)點(diǎn)距的間隔,每行之間也有間隔,起到字符間距和行間距的作用。其實(shí)物圖如下所示:
? ? ? ? ? ?LCD1602有 16 個(gè)管腳孔,從左至右管腳編號(hào)順序是 1-16,其功能定義如下所示
? ? ? ? ? ?管腳說(shuō)明:
? ? ? ? ? ?3 腳:VL,液晶顯示偏壓信號(hào),用于調(diào)整 LCD1602 的顯示對(duì)比度,通常外接電位器用以調(diào)整偏壓信號(hào)。注意,電壓為 0 時(shí)對(duì)比度最強(qiáng)。
? ? ? ? ? ?4 腳:RS,數(shù)據(jù)/命令選擇端。此腳為高電平時(shí),可對(duì)LCD1602 進(jìn)行數(shù)據(jù)字節(jié)(即使用在 LCD1602上顯示的字節(jié),且LCD1602 的數(shù)據(jù)是 8 位的)的傳輸操作;此腳為低電平時(shí),則是進(jìn)行命令字節(jié)(即用來(lái)對(duì) LCD1602 的一些工作方式作設(shè)置的字節(jié))的傳輸操作。
? ? ? ? ? ? 5 腳:R/W,讀寫(xiě)選擇端。此腳為高電平,可對(duì) LCD1602 進(jìn)行讀數(shù)據(jù)操作, 反之進(jìn)行寫(xiě)數(shù)據(jù)操作。
? ? ? ? ? ? 6 腳:E,使能信號(hào),其實(shí)是 LCD1602 的數(shù)據(jù)控制時(shí)鐘信號(hào),利用該信號(hào)的上升沿實(shí)現(xiàn)對(duì) LCD1602 的數(shù)據(jù)傳輸。
? ? ? ? ? ?7~14 腳:8 位并行數(shù)據(jù)口。 51 單片機(jī)一組 IO 也是 8 位,使得對(duì) LCD1602 的數(shù)據(jù)讀寫(xiě)大為方便。 在 LCD1602 內(nèi)部含有 80 個(gè)字節(jié)的數(shù)據(jù)存儲(chǔ)器DDRAM,用來(lái)寄存顯示字符。其地址和屏幕的對(duì)應(yīng)關(guān)系如下表所示:
| 顯示位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | .... | 40 | |
| DDRAM地址 | 第一行 | 00H | 01H | 02H | 03H | 04H | 05H | 06H | .... | 27H |
| 第二行 | 40H | 41H | 42H | 43H | 44H | 45H | 46H | .... | 67H |
? ? ? ? ? ??如圖所示,并非所有的地址都可直接用來(lái)顯示字符數(shù)據(jù),只有第一行中的 00-0F、第二行中的 40-4F 才能顯示,其他地址只能用于存儲(chǔ)。要顯示字符時(shí),要先輸入顯示字符地址,也就是告訴模塊在哪里顯示字符。
? ? ? ? ? ??例如第二行第一個(gè)字符的地址是 40H,那么是否直接寫(xiě)入 40H 就可以將光標(biāo)定位在第二行第一個(gè)字符的位置呢?這樣不行,因?yàn)?span style="color:#fe2c24;">寫(xiě)入顯示地址時(shí)要求最高位 D7 恒定為高電平 1 。
? ? ? ? ? ??所以實(shí)際寫(xiě)入的數(shù)據(jù)應(yīng)該是 01000000B(40H) +10000000B(80H)=11000000B(C0H)。在 LCD1602 中就用前 16 個(gè)就行了。第二行也一樣用前 16 個(gè)地址。
LCD1602 常用指令
? ? ? ? ? ???使用 LCD1602 需要掌握的一些常用的指令:
清屏指令?
- ?清除液晶顯示器,即將 DDRAM 的內(nèi)容全部填入"空白"的 ASCII 碼 20H;
- 光標(biāo)歸位,即將光標(biāo)撤回液晶顯示屏的左上方;
- 將地址計(jì)數(shù)器(AC)的值設(shè)為 0。
| 指令功能 | 指令編碼 | 執(zhí)行時(shí)間/ms | |||||||||
| RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | ||
| 清屏 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1.64 |
模式設(shè)置指令
- 設(shè)定每次寫(xiě)入 1 位數(shù)據(jù)后光標(biāo)的移位方向,并且設(shè)定每次寫(xiě)入的一個(gè)字符是否移動(dòng)
- I/D:? 0=寫(xiě)入新數(shù)據(jù)后光標(biāo)左移? ? ? ? ? ? ?1=寫(xiě)入新數(shù)據(jù)后光標(biāo)右移
- S:? ? 0=寫(xiě)入新數(shù)據(jù)后顯示屏不移動(dòng)? ? ? 1=寫(xiě)入新數(shù)據(jù)后顯示屏整體右移 1 個(gè)字符
| 指令功能 | 指令編碼 | 執(zhí)行時(shí)間/us | |||||||||
| RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | ||
| 進(jìn)入模式設(shè)置 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | 40 |
顯示開(kāi)關(guān)控制指令
- 控制顯示器開(kāi)/關(guān)、光標(biāo)顯示/關(guān)閉以及光標(biāo)是否閃爍。
- D:? 0=顯示功能關(guān)? ? ?1=顯示功能開(kāi)
- C:? 0=無(wú)光標(biāo)? ? ? ? ? ? 1=有光
- B:? 0=光標(biāo)閃爍? ? ? ? ?1=光標(biāo)不閃爍?
| 指令功能 | 指令編碼 | 執(zhí)行時(shí)間/us | |||||||||
| RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | ||
| 顯示開(kāi)關(guān)控制 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | C | B | 40 |
功能設(shè)定指令
- 設(shè)定數(shù)據(jù)總線位數(shù)、顯示的行數(shù)及字型。
- DL: 0=數(shù)據(jù)總線為 4 位? ? ? ? ? ? ? ? 1=數(shù)據(jù)總線為 8 位
- N:? ?0=顯示 1 行? ? ? ? ? ? ? ? ? ? ? ? ? ?1=顯示 2 行
- F:? ?0=5×7 點(diǎn)陣/每字符? ? ? ? ? ? ? ? 1=5×10 點(diǎn)陣/每字符
| 指令功能 | 指令編碼 | 執(zhí)行時(shí)間/us | |||||||||
| RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | ||
| 功能設(shè)定 | 0 | 0 | 0 | 0 | 1 | DL | N | F | X | X | 40 |
LCD1602 使用
? ? ? ? ? ???使用 LCD1602,首先需要對(duì)其初始化,即通過(guò)寫(xiě)入一些特定的指令實(shí)現(xiàn)。 然后選擇要在 LCD1602 的哪個(gè)位置顯示并將所要顯示的數(shù)據(jù)發(fā)送到 LCD 的 DDRAM。使用 LCD1602 通常都是用于寫(xiě)數(shù)據(jù)進(jìn)去,很少使用讀功能。LCD1602 操作步驟如下所示:
? ? ? ? ? ???在此,不需要讀出它的數(shù)據(jù)的狀態(tài)或者數(shù)據(jù)本身。所以只需要看兩個(gè)寫(xiě)時(shí)序:
? ? ? ? ? ??? ①當(dāng)要寫(xiě)指令字,設(shè)置 LCD1602 的工作方式時(shí):需要把 RS 置為低電平,RW 置為低電平,然后將數(shù)據(jù)送到數(shù)據(jù)口 D0~D7,最后使能信號(hào) E 引腳一個(gè)高脈沖將數(shù)據(jù)寫(xiě)入。
? ? ? ? ? ??? ②當(dāng)要寫(xiě)入數(shù)據(jù)字,在 1602 上實(shí)現(xiàn)顯示時(shí):需要把 RS 置為高電平,RW 置為低電平,然后將數(shù)據(jù)送到數(shù)據(jù)口 D0~D7,最后使能信號(hào) E 引腳一個(gè)高脈沖將數(shù)據(jù)寫(xiě)入。
? ? ? ? ? ???寫(xiě)指令和寫(xiě)數(shù)據(jù),差別僅僅在于 RS 的電平不一樣而已。以下為 LCD1602 的時(shí)序圖:
? ? ? ? ? ????以上時(shí)間參數(shù)全部是 ns 級(jí)別的,而 51 單片機(jī)的機(jī)器周期是 1us,指令周期是 2-4 個(gè)機(jī)器周期,所以不加延時(shí)程序,也配合 LCD1602 的時(shí)序要求。
? ? ? ? ? ????當(dāng)要寫(xiě)命令字節(jié)的時(shí)候,時(shí)間由左往右,RS 變?yōu)榈碗娖?#xff0c;R/W 變?yōu)榈碗娖?#xff0c; 注意,RS 的狀態(tài)先變化完成。然后?DB0~DB7 上數(shù)據(jù)進(jìn)入有效階段,接著 E 引腳有一個(gè)整脈沖的跳變,接著要維持時(shí)間最小值為 tpw=150ns 的 E 脈沖寬度。然后E引腳負(fù)跳變,RS電平變化,R/W 電平變化。這樣便是一個(gè)完整的LCD1602 寫(xiě)命令的時(shí)序。
? ? ? ? ? ???? 注意:這里介紹的是 8 位 LCD1602。
硬件部分
?
? ? ? ? ? ???? 使用到硬件資源如下:
? ? ? ? ? ???? 開(kāi)發(fā)板上集成了一個(gè) LCD1602 液晶接口,電路如下所示:
? ? ? ? ? ? ? ? ? ? ???? 如圖所示,8 位數(shù)據(jù)口 DB0-DB7 與單片機(jī)的 P0.0-P0.7 管腳連接,RS、RW、E 腳與單片機(jī)的 P2.6、P2.5、P2.7 管腳連接。圖中的RJ1 是一個(gè)電位器,用來(lái)調(diào)節(jié) LCD1602 對(duì)比度即顯示亮度,實(shí)物圖如下所示:
? ? ? ? ? ????注:這里原理圖使用的是 8 位 LCD1602 接口設(shè)計(jì),可兼容 4 位 LCD1602 。 4 位 LCD1602 在傳輸數(shù)據(jù)時(shí),需要將 8 位的數(shù)據(jù)截成兩段,先發(fā)送高四位,后發(fā)低四位。其它引腳操作方法不變。
軟件部分
? ? ? ?? 所要實(shí)現(xiàn)的功能是:在 LCD1602 液晶上顯示字符信息。
? ? ? ?? 程序框架如下:
? ? ? ?? ?重點(diǎn)是對(duì) LCD1602 進(jìn)行寫(xiě)命令和數(shù)據(jù)。 這里分析幾個(gè)重要函數(shù):
?LCD1602 驅(qū)動(dòng)函數(shù)
? ? ? ?? ?在代碼中可以看到有如下格式:
#if (LCD1602_4OR8_DATA_INTERFACE==0) ...(省略?xún)?nèi)容 1) #else ...(省略?xún)?nèi)容 2) #endif? ? ? ?? ?這是 C 語(yǔ)言中的條件編譯,如果條件表達(dá)式 LCD1602_4OR8_DATA_INTERFACE==0 為真, 則執(zhí)行省略?xún)?nèi)容 1 部分,否則執(zhí)行省略?xún)?nèi)容 2 部分。和 if...else 類(lèi)似。?
? ? ? ?? ?lcd1602_write_cmd 函數(shù)是 LCD1602 寫(xiě)命令。
? ? ? ?? ?lcd1602_write_data 函數(shù)是 LCD1602 寫(xiě)數(shù)據(jù),它們之間的區(qū)別僅在于控制腳 RS 的值,如果為 0 則寫(xiě)命令, 為 1 則寫(xiě)數(shù)據(jù)。
? ? ? ?? ?對(duì)于 8 位數(shù)據(jù)和 4 位數(shù)據(jù)口的驅(qū)動(dòng),不同之處在于 8 位數(shù)據(jù)是一 次性傳輸?shù)蕉丝?#xff0c;而 4 位數(shù)據(jù)口需要將一個(gè)字節(jié)數(shù)據(jù)分兩次傳輸,高 4 位和低 4 位。
? ? ? ?? ? lcd1602_init 函數(shù)是 LCD1602 初始化函數(shù),根據(jù)其命令設(shè)置相應(yīng)的值,開(kāi)啟 LCD1602 顯示。
? ? ? ?? ?lcd1602_clear 函數(shù)是 LCD1602 清屏函數(shù),實(shí)際上也是調(diào)用 lcd1602_write_cmd 函數(shù)寫(xiě) 0X01 命令。
? ? ? ?? ?lcd1602_show_string 函數(shù)是 LCD1602 顯示字符函數(shù),該函數(shù)有 3 個(gè)入口參數(shù),x 和 y 用來(lái)確定顯示的坐標(biāo),x 范圍是 0-15,y 范圍是 0-1。str 參數(shù)是一個(gè)指針類(lèi)型變量,用于傳遞顯示的內(nèi)容。函數(shù)內(nèi)首先判斷 x、y 坐標(biāo)是否有效,無(wú)效則強(qiáng)制退出,然后根據(jù) xy 值在對(duì)應(yīng)的坐標(biāo)位置顯示內(nèi)容,代碼如下:
#include "lcd1602.h"/******************************************************************************* * 函 數(shù) 名 : lcd1602_write_cmd * 函數(shù)功能 : LCD1602寫(xiě)命令 * 輸 入 : cmd:指令 * 輸 出 : 無(wú) *******************************************************************************/ #if (LCD1602_4or8_DATA_INTERFACE==0)//8為L(zhǎng)CD void lcd1602_write_cmd(u8 cmd) {LCD1602_RS=0; //選擇命令LCD1602_RW=0; //選擇寫(xiě)LCD1602_E=0;LCD1602_DATAPORT=cmd; //準(zhǔn)備命令delay_ms(1);LCD1602_E=1; //使能腳E先上升沿寫(xiě)入delay_ms(1);LCD1602_E=0; //使能腳E后負(fù)跳變完成寫(xiě)入 } #else //4位LCD /*對(duì)于 4 位 LCD1602 在傳輸數(shù)據(jù)的時(shí)候需要將 8 位的數(shù)據(jù)截成兩段,先發(fā) 送高四位,在發(fā)送低四位。其它引腳操作方法不變。*/ void lcd1602_write_cmd(u8 cmd) {LCD1602_RS=0; //選擇命令LCD1602_RW=0; //選擇寫(xiě)LCD1602_E=0;LCD1602_DATAPORT=cmd; //準(zhǔn)備命令,發(fā)送高四位delay_ms(1);LCD1602_E=1; //使能腳E先上升沿寫(xiě)入delay_ms(1);LCD1602_E=0; //使能腳E后負(fù)跳變完成寫(xiě)入LCD1602_DATAPORT=cmd<<4; //準(zhǔn)備命令,發(fā)送低四位,此時(shí)將低四位左移至高四位再發(fā)送delay_ms(1);LCD1602_E=1; //使能腳E先上升沿寫(xiě)入delay_ms(1);LCD1602_E=0; //使能腳E后負(fù)跳變完成寫(xiě)入 } #endif/******************************************************************************* * 函 數(shù) 名 : lcd1602_write_data * 函數(shù)功能 : LCD1602寫(xiě)數(shù)據(jù) * 輸 入 : dat:數(shù)據(jù) * 輸 出 : 無(wú) *******************************************************************************/ #if (LCD1602_4or8_DATA_INTERFACE==0) //8位LCD void lcd1602_write_data(u8 dat) {LCD1602_RS=1; //選擇數(shù)據(jù)LCD1602_RW=0; //選擇寫(xiě)LCD1602_E=0;LCD1602_DATAPORT=dat; //準(zhǔn)備數(shù)據(jù)delay_ms(1);LCD1602_E=1; //使能腳E先上升沿寫(xiě)入delay_ms(1);LCD1602_E=0; //使能腳E后負(fù)跳變完成寫(xiě)入 } #else void lcd1602_write_data(u8 dat) {LCD1602_RS=1; //選擇數(shù)據(jù)LCD1602_RW=0; //選擇寫(xiě)LCD1602_E=0;LCD1602_DATAPORT=dat; //準(zhǔn)備數(shù)據(jù),發(fā)送高四位delay_ms(1);LCD1602_E=1; //使能腳E先上升沿寫(xiě)入delay_ms(1);LCD1602_E=0; //使能腳E后負(fù)跳變完成寫(xiě)入LCD1602_DATAPORT=dat<<4; //準(zhǔn)備新數(shù)據(jù),發(fā)送低四位,此時(shí)將低四位左移至高四位再發(fā)送delay_ms(1);LCD1602_E=1; //使能腳E先上升沿寫(xiě)入delay_ms(1);LCD1602_E=0; //使能腳E后負(fù)跳變完成寫(xiě)入 } #endif/******************************************************************************* * 函 數(shù) 名 : lcd1602_init * 函數(shù)功能 : LCD1602初始化 * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ #if (LCD1602_4or8_DATA_INTERFACE==0) //8位LCD void lcd1602_init(void) {lcd1602_write_cmd(0x38); //功能設(shè)定指令:數(shù)據(jù)總線8位,顯示2行,5*7點(diǎn)陣/字符lcd1602_write_cmd(0x0c); //顯示開(kāi)關(guān)控制指令:顯示功能開(kāi),無(wú)光標(biāo),光標(biāo)閃爍lcd1602_write_cmd(0x06); //模式設(shè)置指令:寫(xiě)入新數(shù)據(jù)后光標(biāo)右移,顯示屏不移動(dòng)lcd1602_write_cmd(0x01); //清屏指令:清屏 } #else void lcd1602_init(void) {lcd1602_write_cmd(0x28); //功能設(shè)定指令:數(shù)據(jù)總線4位,顯示2行,5*7點(diǎn)陣/字符lcd1602_write_cmd(0x0c); //顯示開(kāi)關(guān)控制指令:顯示功能開(kāi),無(wú)光標(biāo),光標(biāo)閃爍lcd1602_write_cmd(0x06); //模式設(shè)置指令:寫(xiě)入新數(shù)據(jù)后光標(biāo)右移,顯示屏不移動(dòng)lcd1602_write_cmd(0x01); //清屏指令:清屏 } #endif/******************************************************************************* * 函 數(shù) 名 : lcd1602_clear * 函數(shù)功能 : LCD1602清屏 * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ void lcd1602_clear(void) {lcd1602_write_cmd(0x01); }/******************************************************************************* * 函 數(shù) 名 : lcd1602_show_string * 函數(shù)功能 : LCD1602顯示字符 * 輸 入 : x,y:顯示坐標(biāo),x=0~15,y=0~1;str:顯示字符串 * 注 釋 : 并非所有的地址都可直接用來(lái)顯示字符數(shù)據(jù),只有第一行中的 00-0F、第二行中的 40-4F 才能顯示,其他地址只能用于存儲(chǔ)。 *******************************************************************************/ void lcd1602_show_string(u8 x,u8 y,u8 *str) {u8 i=0;if(y>1||x>15) //行列參數(shù)無(wú)效,強(qiáng)制退出return;if(y<1) //第一行顯示{while(*str!='\0'){if(i<16-x){lcd1602_write_cmd(0x80+i+x);}else {lcd1602_write_cmd(0x40+0x80+i+x-16);}lcd1602_write_data(*str);str++;i++;} }else{while(*str!='\0'){if(i<16-x) //如果字符長(zhǎng)度超過(guò)第二行顯示范圍,則在第一行繼續(xù)顯示{lcd1602_write_cmd(0x80+0x40+i+x);}else {lcd1602_write_cmd(0x80+i+x-16);}lcd1602_write_data(*str);str++;i++;} } }主函數(shù)
? ? ? ?? ?首先調(diào)用外設(shè)驅(qū)動(dòng)頭文件,然后進(jìn)入 main 函數(shù)初始化 LCD1602,并調(diào)用 LCD1602 顯示函數(shù)讓第一行顯示"Hello World!",第二行顯 示"0123456789"。
#include "public.h" #include "lcd1602.h"void main() {lcd1602_init(); //LCD1602初始化lcd1602_show_string(0,0,"Hello world!"); //第一行顯示lcd1602_show_string(0,1,"0123456789"); //第二行顯示while(1){} }? ? ? ?? ?這里說(shuō)明下,在開(kāi)發(fā)中通常會(huì)顯示數(shù)值,比如溫度數(shù)據(jù),程序中我們獲取的溫度數(shù)據(jù)通常存儲(chǔ)在 float 變量中,并非字符串,此時(shí)需要想辦法將 float 變量中的值轉(zhuǎn)換為字符串,比如 float temp=31.2,那么我們可以再定義一個(gè)數(shù)組 temp_buf[]用于保存 temp 中的每一個(gè)位,操作如下:
float temp=31.2; u8 temp_buf[5]; u16 temp_value=temp*10;//將浮點(diǎn)數(shù)轉(zhuǎn)換為整型變量,乘10得312/*獲取temp)value的各位,并存儲(chǔ)在數(shù)組temp_value中*/ temp_buf[0]=temp_value/100+0x30; temp_buf[1]=temp_value%100/10+0x30; temp_buf[2]='.'; temp_buf[3]=temp_value%100%10+0x30; temp_buf[4]='\0'; lcd1602_show_string(0,0,temp_buf);? ? ? ?? ?將浮點(diǎn)數(shù)轉(zhuǎn)換為整型變量,然后將整型值的每一個(gè)位取出來(lái)存儲(chǔ)在數(shù)組 temp_buf 中,取出的每一位后面加了 0X30,這個(gè)值是將數(shù)字 0-9 轉(zhuǎn)換為 ASCII 碼,因?yàn)橐壕且?ASCII 碼顯示的。最后一個(gè)數(shù)組元素賦值 了’\0’,這是為了讓 LCD1602 顯示函數(shù)知道數(shù)組內(nèi)結(jié)束位置。
? ? ? ?? ?根據(jù) C 語(yǔ)言指針的特點(diǎn),此時(shí)調(diào)用 LCD1602 顯示函數(shù)時(shí),只需要將數(shù)組名傳遞進(jìn)去即可,因?yàn)閿?shù)組名即為該數(shù)組的起始地址,然后顯示函數(shù)內(nèi)部通過(guò)指針訪問(wèn)數(shù)組的每一位。
現(xiàn)象
? ? ? ? 實(shí)現(xiàn)現(xiàn)象如下:在 LCD1602 液晶上顯示字符信息。
?
總結(jié)
以上是生活随笔為你收集整理的LCD1602 液晶显示实验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 微型计算机组装的目的,微机组装实训报告范
- 下一篇: matlab静电场有限元分析