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