簡介
工業字元型液晶,能夠同時顯示16x02即32個字元。(16列2行)
註:為了表示的方便 ,後文皆以1表示高電平,0表示低電平。
管腳功能
1602字元型LCD通常有14條引腳線或16條引腳線的LCD,多出來的2條線是背光電源線
VCC(15腳)和地線GND(16腳),其控制原理與14腳的LCD完全一樣,其中:
引腳 | 符號 | 功能說明 |
1 | VSS | 一般接地 |
2 | VDD | 接電源(+5V) |
3 | V0 | 液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高(對比度過高時會產生“鬼影”,使用時可以通過一個10K的電位器調整對比度)。 |
4 | RS | RS為暫存器選擇,高電平1時選擇數據暫存器、低電平0時選擇指令暫存器。 |
5 | R/W | R/W為讀寫信號線,高電平(1)時進行讀操作,低電平(0)時進行寫操作。 |
6 | E | E(或EN)端為使能(enable)端, 寫操作時,下降沿使能。 讀操作時,E高電平有效 |
7 | DB0 | 低4位三態、 雙向數據匯流排 0位(最低位) |
8 | DB1 | 低4位三態、 雙向數據匯流排 1位 |
9 | DB2 | 低4位三態、 雙向數據匯流排 2位 |
10 | DB3 | 低4位三態、 雙向數據匯流排 3位 |
11 | DB4 | 高4位三態、 雙向數據匯流排 4位 |
12 | DB5 | 高4位三態、 雙向數據匯流排 5位 |
13 | DB6 | 高4位三態、 雙向數據匯流排 6位 |
14 | DB7 | 高4位三態、 雙向數據匯流排 7位(最高位)(也是busy flag) |
15 | BLA | 背光電源正極 |
16 | BLK | 背光 電源負極 |
暫存器選擇控制表
RS | R/W | 操作說明 |
0 | 0 | 寫入指令暫存器(清除屏等) |
0 | 1 | 讀busy flag(DB7),以及讀取位址計數器(DB0~DB6)值 |
1 | 0 | 寫入數據暫存器(顯示各字型等) |
1 | 1 | 從數據暫存器讀取數據 |
註:關於E=H脈衝——開始時初始化E為0,然後置E為1,再清0.
busy flag(DB7):在此位為1時,LCD忙,將無法再處理其他的指令要求。
字元集
1602液晶模組內部的字元發生
存儲器(
CGROM)已經存儲了160個不同的
點陣字元圖形,這些字元有:阿拉伯數字、英文字母的大小寫、常用的符號、和日文假名等,每一個字元都有一個固定的代碼,比如大寫的英文字母“A”的代碼是01000001B(41H),顯示時模組把地址41H中的點陣字元圖形顯示出來,我們就能看到字母“A”。
因為1602識別的是ASCII碼,試驗可以用ASCII碼直接賦值,在
單片機編程中還可以用字元型
常量或變數賦值,如'A’。
以下是1602的16進制ASCII碼錶:
(圖片打開是大圖)
讀的時候,先讀上面那行,再讀左邊那列,如:感嘆號!的ASCII為0x21,字母B的ASCII為0x42(前面加0x表示十六進制)。
顯示地址
1602字元液晶顯示可分為上下兩部分各16位進行顯示,處於不同行時的字元顯示地址如下
顯示字元 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
第一行 地址 | 00H | 01H | 02H | 03H | 04H | 05H | 06H | 07H | 08H | 09H | 0AH | 0BH | 0CH | 0DH | 0EH | 0FH |
第二行 地址 | 40H | 41H | 42H | 43H | 44H | 45H | 46H | 47H | 48H | 49H | 4AH | 4BH | 4CH | 4DH | 4EH | 4FH |
指令集
1602通過D0~D7的8位數據端傳輸數據和指令。
顯示模式設定:(初始化)
0011 1000
[0x38]設定16×2顯示,5×8
點陣,8位數據接口;
0000 1DCB D顯示(1有效)、C游標顯示(1有效)、B游標閃爍(1有效)
0000 01NS N=1(讀或寫一個字元後地址
指針加1 &游標加1),
N=0(讀或寫一個字元後地址指針減1 &游標減1),
S=1 且 N=1 (當寫一個字元後,整屏顯示左移)
s=0 當寫一個字元後,整屏顯示不移動
數據指針設定:
數據首地址為80H,所以數據地址為80H+
地址碼(0-27H,40-67H)
其他設定:
01H(顯示清屏,數據
指針=0,所有顯示=0);02H(顯示回車,數據指針=0)。
通常推薦的初始化過程:
延時15ms
寫指令38H
延時5ms
寫指令38H
延時5ms
寫指令38H
延時5ms
(以上都不檢測忙信號)
(以下都要檢測忙信號)
寫指令38H
寫指令08H 關閉顯示
寫指令01H 顯示清屏
寫指令0cH 顯示開及游標設定
完畢
Proteus仿真
使用Proteus仿真1602--即LM016L--依照數據手冊說明可能遇到困難,可以嘗試採用以下方案解決:
1、數據手冊中可能介紹1602內部D0~D7已有上拉,可以使用P0口直接驅動。在Proteus里LM016L內部可能沒有,應該人為
加上拉電阻。建議不要使用排阻,使用普通電阻一個一個拉應該可以解決問題;
2、可能碰到不能檢測忙信號的問題,嘗試使用延時把忙信號拖過去。
時序圖
基本的讀寫時序圖
讀寫操作時序如圖1和2所示:
寫操作時序:
讀操作時序:
程式代碼
(參考)
/#include<intrins.h> //包含NOP空指令的頭檔案
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_H 1 //宏定義手冊中出現的H的定義
#define LCD1602_L 0 //宏定義手冊中出現的L的定義
#define LCD1602_DAT 1 //數據
#define LCD1602_COM 0 //命令
#define LCD_15MS 300 //宏定義15MS延時需要的數值
#defineLCD_5MS 100 //宏定義 5MS延時需要的數值
/*顯示模式指令*/
#define LCD_Display_mode 0X38 //設定16x2顯示 5x7點陣 8位數據接口
/*顯示開/關及游標設定*/
#define LCD_shows0 0X0C //開顯示 不顯示游標 游標不閃爍
#define LCD_shows2 0X0E //開顯示 顯示游標 游標不閃爍
#define LCD_shows1 0X0F //開顯示 顯示游標 游標 閃爍
#define LCD_shows3 0X08 //關顯示 不顯示游標 游標不閃爍
/*指針設定*/
#define LCD_cursor1 0X04 //寫一個字元 地址指針減1
#define LCD_cursor2 0X05 //寫一個字元 地址指針減1 並螢幕右移
#define LCD_cursor3 0X06 //寫一個字元 地址指針加1
#define LCD_cursor4 0X07 //寫一個字元 地址指針加1 並螢幕左移
/*清屏指令*/
#define LCD_clear 0x01 //清屏指令 數據指針清零 所有顯示清零
/*忙狀態字*/
#define LCD_WAY 0x80 //狀態字
/*宏定義顯示起始地址*/
#define LCD_ADDH 0X80 //第一行地址0x80-0xA7
#define LCD_ADDL 0XC0 //第二行地址0xC0-0xE7
/*IO口定義*/
#define LCD1602_DATA P0 //宏定義8位數據線IO為P0口 D0~D7=P00~P07 8位數據線 D0=P00;
sbit LCD1602_RS=P2^5; //數據/命令選擇端(H/L)
sbit LCD1602_RW=P2^6; //讀/寫選擇端(H/L)
sbit LCD1602_E =P2^7; //使能信號
/*函式聲明*/
void LCD1602_init(); //液晶初始化函式
void LCD1602_writecd(bit lcd_rs, uchar LCD1602_d);//寫命令/數據 函式bit lcd_rs是數據還是命令 uchar LCD1602_d要寫入的數據
uchar LCD1602_readway(); //讀忙狀態函式 由寫入和讀取函式調用
uchar LCD1602_readata(); //讀數據函式
void LCD_DELAY(uchar LCD_delay); //
/*液晶初始化函式*/
void LCD1602_init() //液晶初始化函式
{ LCD_DELAY(LCD_15MS); //延時15MS 初始化
LCD1602_writecd(LCD1602_COM,LCD_Display_mode);//寫指令38H 設定16x2顯示 5x7點陣 8位數據接口
LCD1602_writecd(LCD1602_COM,LCD_shows0); //開顯示 不顯示游標 游標不閃爍
LCD1602_writecd(LCD1602_COM,LCD_cursor1); //檢查忙狀態
LCD1602_writecd(LCD1602_COM,LCD_clear); //寫指令01H:顯示清屏
}
/*液晶寫命令/數據函式*/
void LCD1602_writecd(bit lcd_rs, uchar LCD1602_cd)//寫命令/數據 函式
{ uchar LCD1602_NUM; //定義變數用來液晶無忙回答的退出死循環
LCD1602_NUM=255; //忙狀態檢測次數
while(LCD1602_readway()) //檢查忙狀態
{LCD1602_NUM--; //檢測次數自減
if(LCD1602_NUM==0) //判斷檢測次數等於0
{break;} //退出循環判斷忙
}
LCD1602_RW = LCD1602_L; //讀/寫選擇端(H/L)
LCD1602_RS = lcd_rs; //數據/命令選擇端(H/L)
LCD1602_DATA= LCD1602_cd; //IO口賦值
LCD1602_E = LCD1602_H; //拉高使能信號開始傳輸數據
LCD1602_E = LCD1602_L; //拉低使能信號鎖存數據
LCD1602_DATA= 0xff; //IO口數據清除
}
/*忙狀態讀取函式*/
uchar LCD1602_readway()//讀狀態函式由寫入和讀取函式調用
{ uchar LCD1602_way; //狀態字變數
LCD1602_DATA=0xff; //IO口數據清除
LCD1602_RS = LCD1602_COM; //數據/命令選擇端(H/L) 命令
LCD1602_RW = LCD1602_H; //讀/寫選擇端(H/L)
LCD1602_E = LCD1602_H; //拉高使能信號開始接收狀態
LCD1602_way =LCD1602_DATA; //讀取狀態
LCD1602_E = LCD1602_L; //拉低使能信號鎖存數據
LCD1602_way =LCD1602_way&LCD_WAY;//取忙狀態字
return(LCD1602_way); //返回狀態字
}
/*液晶讀數據函式*/
uchar LCD1602_readata()//讀數據函式
{ uchar LCD1602_data; //數據暫存變數
while(LCD1602_readway()); //檢查忙狀態 --------------------
LCD1602_DATA=0xff; //IO口數據清除
LCD1602_RS = LCD1602_DAT; //數據/命令選擇端(H/L) 數據
LCD1602_RW = LCD1602_H; //讀/寫選擇端(H/L)
LCD1602_E = LCD1602_H; //拉高使能信號開始接收狀態
LCD1602_data= LCD1602_DATA; //讀取狀態
LCD1602_E = LCD1602_L; //拉低使能信號鎖存數據
return(LCD1602_data); //返回數據
}
/*延時函式*/
void LCD_DELAY(uchar LCD_delay)//
{ uchar lcd_del;
while(LCD_delay--) //自減
{lcd_del=100;
while(lcd_del--);}
}