51微控制器簡單的驅動LCD1602
目錄
CSDN始於python,終究還是要回到自己老本行,學一學py只是一時興起,為了自己興趣,電信才是自己的真愛。
【LCD1602】
什麼是LCD1602
LCD1602是一種工業字元型液晶,能夠同時顯示16x02即32個字元。LCD1602液晶顯示的原理是利用液晶的物理特性,通過電壓對其顯示區域進行控制,即可以顯示出圖形。
1602液晶也叫1602字元型液晶,它是一種專門用來顯示字母、數字、符號等的點陣
1602LCD是指顯示的內容為16X2,即可以顯示兩行,每行16個字元液晶模組(顯示字元和數字)。
市面上字元液晶大多數是基於HD44780液晶晶片的,控制原理是完全相同的,因此基於HD44780寫的控制程式可以很方便地應用於市面上大部分的字元型液晶。
注意:LCD1602僅能顯示字母、符號或數字,無法顯示漢字。
LCD1602管腳
狀態字
RAM地址對映
控制器介面時序
1、讀操作時序
2、寫操作時序
3、時序引數
基本操作時序
1602的基本操作時序一共有4個,下面一一介紹。
寫程式前我們先將用到的匯流排介面做一個同意宣告:
#define LCD1602_DB P2 //並行輸入口
sbit LCD1602_RS = P0^5; //資料/命令選擇端
sbit LCD1602_RW = P0^6; //讀寫選擇端
sbit LCD1602_EN = P0^7; //使能端
<1>讀狀態:RS = L,R/W = H,EN = H
LCD1602_DB = 0xFF; LCD1602_RS = 0; LCD1602_RW = 1; LCD1602_EN = 1; sta = LCD1602_DB;
這樣就把當前液晶的狀態字讀到了sta這個變數中,可以通過判斷sta最高位的值來了解當前液晶是否處於“忙”狀態,也可以得知當前資料的指標位置。
<2>讀資料:RS = H,R/W = H,EN = H
在實際使用時,讀資料很少使用,大家可以僅瞭解就行。
<3>寫指令:RS = L,R/W = L,D0~D7 = 指令碼,EN = 高脈衝
在這裡就E = 高脈衝需要了解一下。因為這一句很關鍵,當前狀態是寫資料,根據時序圖,首先保證EN引腳是低電平狀態,不管前三句之前怎麼設定,1602這裡EN引腳沒有使能控制,就不會讀總線上的訊號。當前三句準備好之後,讓EN引腳從低電平到高電平變化,然後EN引腳再從高電平到低電平出現一個下降沿,1602檢測到這個下降沿之後,並且檢測到RS = L,R/W = L,就會馬上讀取D0~D7的資料,完成微控制器寫1602指令的過程。
歸納:EN使能引腳先低拉高,再從高拉低,形成一個高脈衝。
<4>寫資料:RS = H,R/W = L,D0~D7 = 資料,EN = 高脈衝
寫資料與寫指令類似,就是把RS改成H,把匯流排改成資料而已。
指令介紹
1、顯示模式設定
寫指令0x38:設定16×2顯示,5×7點陣,8位資料介面。(這條指令是固定的,必須寫0x38)
2、顯示開/關以及游標設定指令
如下圖所示:
第一條指令:一個位元組中8位,前5位是固定的0B0001,低3位分別用DCB從高到低表示
第二條指令:高6位是固定的0B000001,低2位使用NS從高到低表示
3、清屏指令
寫入0x01表示顯示清屏(固定的),其中包含了資料指標清零,所有的顯示清零。
寫入0x02僅僅是資料指標清零,顯示不清零。
4、RAM地址設定指令
該指令的最高位為1,低7位為RAM地址,RAM地址與液晶上字元的關係如上圖所示。通常在讀寫資料之前都要先設定好地址,然後再進行資料的讀寫操作。
5、初始化過程
延時15ms
寫指令38H(不檢測忙訊號)
延時5ms
寫指令38H(不檢測忙訊號)
延時5ms
寫指令38H(不檢測忙訊號)
(以後每次寫指令、讀/寫資料操作前,都要檢測忙訊號)
寫指令38H:顯示模式設定
寫指令08H:顯示關閉
寫指令01H:顯示清屏
寫指令06H:顯示游標移動設定
寫指令0CH:顯示開及游標設定
電路圖
或者可以參考下圖
【程式】
關於LCD1602的參考程式,我在這裡放兩個,一個是自己最開始做51小車時寫的關於LCD1602的程式,以下程式僅供參考
/*寫命令*/
void Write_Cmd(uchar cmd)
{
LCD1602_RS = 0; //寫入命令
LCD1602_RW = 0;
LCD1602_DB = cmd;
Delay_10us(10);
LCD1602_EN = 1; //使能端高電平
Delay_10us(10);
LCD1602_EN = 0;
}
/*寫資料*/
void Write_Dat(uchar dat)
{
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
Delay_10us(10);
LCD1602_EN = 1; //使能端高電平
Delay_10us(10);
LCD1602_EN = 0;
}
/*LCD1602初始化*/
void LCD_INIT()
{
Write_Cmd(0x38); //設定顯示模式
Write_Cmd(0x0c); //開顯示不顯示游標,游標不閃爍
Write_Cmd(0x06); //寫一個指標+1
Write_Cmd(0x01); //清屏
Write_Cmd(0x80); //設定資料指標起點
}
/*延時函式*/
void Delay_10us(uint n)
{
while(n--)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/*LCD1602顯示*/
void Print_LCD1602()
{
uint i,j;
Write_Cmd(0x80); //寫第1行
for(i = 0;i < 6;i++)
Write_Dat(str1[i]);
for(i = 0;i < 4;i++)
Write_Dat(disdata[i]);
for(i = 0;i < 4;i++)
Write_Dat(str2[i]);
Write_Dat(0x20);
if(HAA == 1)
Write_Dat('B');
else if(HAA == 0)
Write_Dat('T');
Write_Cmd(0x80 + 0x40); //寫第2行
for(j = 0;j < 9;j++)
Write_Dat(str3[j]);
for(j = 0;j < 4;j++)
Write_Dat(distance[j]);
for(j = 0;j < 2;j++)
Write_Dat(str4[j]);
}
另一個是自己後來多瞭解之後看的
#define LCD1602_DB P2 //並行輸入口
sbit LCD1602_RS = P0^5; //資料/命令選擇端
sbit LCD1602_RW = P0^6; //讀寫選擇端
sbit LCD1602_EN = P0^7; //使能端
void main()
{
LCD1602_Init();
LCD1602_Show(2,0,"Xiaomo_HAA");
LCD1602_Show(0,11,"HAppy!");
}
//等待液晶準備好
void LCD1602_wait()
{
unsigned char sta;
LCD1602_DB = 0xff;
LCD1602_RS = 0;
LCD1602_RW = 1;
do{
LCD1602_EN = 1;
sta = LCD1602_DB; //讀取狀態字
LCD1602_EN = 0;
}while(sta & 0x80); //bit7等於1表示液晶正忙,重複檢測直到其為0為止
}
//寫命令
void LCD1602_cmd(unsigned char cmd)
{
LCD1602_wait();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_EN = 1;
LCD1602_EN = 0;
}
//寫資料
void LCD1602_Data(unsigned char dat)
{
LCD1602_wait();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_EN = 1;
LCD1602_EN = 0;
}
//設定顯示RAM起始地址(x,y對應螢幕上字元座標)
void LCD1602_SetRAM(unsigned char x,unsigned char y)
{
unsigned char addr;
if(y == 0)
addr = 0x00 + x;
else
addr = 0x40 + x;
LCD1602_cmd(addr | 0x80);
}
//顯示字串
void LCD1602_Show(unsigned char x,unaigned y,unsigned char *str)
{
LCD1602_SetRAM(x,y);
while(*str != '\0')
{
LCD1602_Data(*str++);
}
}
//初始化LCD1602
void LCD1602_Init()
{
Write_Cmd(0x38); //設定顯示模式
Write_Cmd(0x0c); //開顯示不顯示游標,游標不閃爍
Write_Cmd(0x06); //寫一個指標+1
Write_Cmd(0x01); //清屏
}