全方位解析LCD1602特性及單片機顯示應用
1602液晶也叫1602字符型液晶,它是一種專門用來顯示字母、數字、符號等的點陣型液晶模塊。它由若干個5X7或者5X11等點陣字符位組成,每個點陣字符位都可以顯示一個字符,每位之間有一個點距的間隔,每行之間也有間隔,起到了字符間距和行間距的作用,正因為如此所以它不能很好地顯示圖形(用自定義CGRAM,顯示效果也不好)。
本文引用地址:http://2s4d.com/article/201710/366245.htm
LCD1602
LCD1602是指顯示的內容為16X2,即可以顯示兩行,每行16個字符液晶模塊(顯示字符和數字)。
市面上字符液晶大多數是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780寫的控制程序可以很方便地應用于市面上大部分的字符型液晶。
LCD1602—特性
+5V電壓,對比度可調
內含復位電路
提供各種控制命令,如:清屏、字符閃爍、光標閃爍、顯示移位等多種功能
有80字節(jié)顯示數據存儲器DDRAM
內建有192個5X7點陣的字型的字符發(fā)生器CGROM
8個可由用戶自定義的5X7的字符發(fā)生器CGRAM
1602LCD采用標準的14腳(無背光)或16腳(帶背光)接口
LCD1602—引腳功能介紹
第1腳:VSS為電源地
第2腳:VDD接5V電源正極
第3腳:V0為液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高(對比度過高時會 產生“鬼影”,使用時可以通過一個10K的電位器調整對比度)。
第4腳:RS為寄存器選擇,高電平1時選擇數據寄存器、低電平0時選擇指令寄存器。
第5腳:RW為讀寫信號線,高電平(1)時進行讀操作,低電平(0)時進行寫操作。
第6腳:E(或EN)端為使能(enable)端。
第7~14腳:D0~D7為8位雙向數據端。
第15~16腳:空腳或背燈電源。15腳背光正極,16腳背光負極。
LCD1602—指令說明及時序
指令1:清顯示,指令碼01H,光標復位到地址00H位置。
指令2:光標復位,光標返回到地址00H。
指令3:光標和顯示模式設置 I/D:光標移動方向,高電平右移,低電平左移 S:屏幕上所有文字是否左移或者右移。高電平表示有效,低電平則無效。
指令4:顯示開關控制。 D:控制整體顯示的開與關,高電平表示開顯示,低電平表示關顯示 C:控制光標的開與關,高電平表示有光標,低電平表示無光標 B:控制光標是否閃爍,高電平閃爍,低電平不閃爍。
指令5:光標或顯示移位 S/C:高電平時移動顯示的文字,低電平時移動光標。
指令6:功能設置命令 DL:高電平時為4位總線,低電平時為8位總線 N:低電平時為單行顯示,高電平時雙行顯示 F: 低電平時顯示5x7的點陣字符,高電平時顯示5x10的點陣字符。
指令7:字符發(fā)生器RAM地址設置。
指令8:DDRAM地址設置。
指令9:讀忙信號和光標地址 BF:為忙標志位,高電平表示忙,此時模塊不能接收命令或者數據,如果為低電平表示不忙。
指令10:寫數據。
指令11:讀數據。
控制命令表
LCD的管腳控制
LCD1602——寄存器
1602絕大多數是基于HD44780液晶芯片的,HD44780內置了DDRAM、CGROM和CGRAM,這三個都是存儲器。
CGROM(中文字庫)、HCGROM(ASCII碼字庫)及CGRAM(自定義字形)、顯示數據RAM(DDRAM)、字符顯示RAM緩沖區(qū)(DDRAM)
但一行有40個地址,我們只用到前16個地址,第二行也是用前16個地址,對應地址如下
DDRAM(顯示數據存儲RAM)
若想要在屏幕的第一行第一列顯示“A”字符,就要在DDRAM的00H地址寫入“A”的代碼就行了。
我們向DDRAM里的00H地址送數據時,如數字1的代碼,但是并不能顯示1出來。這是我們最容易出錯的地方,若想向00H處顯示數據,則必須將00H加上80H,即0X80H+0X00H,若在01H處則為0X80H+0X01H,依次類推~
LCD1602—CGROM
1602液晶模塊內部的字符發(fā)生存儲器(CGROM)已經存儲了160個不同的點陣字符圖形。這些字符有:阿拉伯數字、英文字母的大小寫、常用的符號、和日文假名等,每一個字符都有一個固定的代碼
從上表可以看出最左邊一列是供用戶自定義字符的,共有16個,實際只有8個字節(jié)可以用,字符碼為00000000—00000111這8個地址
LCD1602—顯示應用(單片機學習)
LCD1602是51單片機中很重要的模塊之一,為了方便新手學習1602,筆者把自己學習1602的一些心得體會拿出來和菜鳥分享,因筆者水平有限,錯誤在所難免,望大家指正。本文程序基于慧凈HJ-1G51開發(fā)板。很多程序為本人自己編寫,可以直接拿去用。
一、關于LCD1602:
在編寫LCD1602程序前,我們必須了解其手冊上一些非常重要的信息,如果這些信息不能理解透徹,編程可能會遇到或多或少的問題,在此先大致歸納幾點。
1.管腳:
1602共16個管腳,但是編程用到的主要管腳不過三個,分別為:RS(數據命令選擇端),R/W(讀寫選擇端),E(使能信號);以后編程便主要圍繞這三個管腳展開進行初始化,寫命令,寫數據。
以下具體闡述這三個管腳:
RS為寄存器選擇,高電平選擇數據寄存器,低電平選擇指令寄存器。
R/W為讀寫選擇,高電平進行讀操作,低電平進行寫操作。
E端為使能端,后面和時序聯系在一起。
除此外,D0~D7分別為8位雙向數據線。
2.操作時序:
RS
R/W
操作說明
0
0
寫入指令碼D0~D7
0
1
讀取輸出的D0~D7狀態(tài)字
1
0
寫入數據D0~D7
1
1
從D0~D7讀取數據
注:關于E=H脈沖——開始時初始化E為0,然后置E為1,再清0.
讀取狀態(tài)字時,注意D7位,D7=1,禁止讀寫操作;D7=0,允許讀寫操作;
所以對控制器每次進行讀寫操作前,必須進行讀寫檢測。(即后面的讀忙子程序)
3.指令集:
LCD_1602 初始化指令小結:
0x38
設置16*2顯示,5*7點陣,8位數據接口
0x01
清屏
0x0F
開顯示,顯示光標,光標閃爍
0x08
只開顯示
0x0e
開顯示,顯示光標,光標不閃爍
0x0c
開顯示,不顯示光標
0x06
地址加1,當寫入數據的時候光標右移
0x02
地址計數器AC=0;(此時地址為0x80)
光標歸原點,但是DDRAM中斷內容不變
0x18
光標和顯示一起向左移動
4.顯示地址:
LCD1602內部RAM顯示緩沖區(qū)地址的映射圖,00~0F、40~4F分別對應LCD1602的上下兩行的每一個字符,只要往對應的RAM地址寫入要顯示字符的ASCII代碼,就可以顯示出來。
5.讀寫時序:
時序圖1602手冊中有,這里不引用了。時序圖很重要,編程就是根據時序圖設置寄存器,讓LCD工作。
二、LCD1602程序編寫流程:
LCD1602在了解完以上信息后便可以編寫,這里我們把程序分為以下幾步:
1.定義LCD1602管腳,包括RS,R/W,E。這里定義是指這些管腳分別接在單片機哪些I/O口上。
現舉例如下:
sbit EN=P3^4;
sbit RS=P3^5;
sbit RW=P3^6;
2.顯示初始化,在這一步進行初始化及設置顯示模式等操作,包括以下步驟:
設置顯示方式
延時
清理顯示緩存
設置顯示模式
通常推薦的初始化過程如下:
延時15ms
寫指令38H
延時5ms
寫指令38H
延時5ms
寫指令38H
延時5ms
注:以上寫38H指令可以看情況省略1~2步
?。ㄒ陨隙疾粰z測忙信號)
?。ㄒ韵露家獧z測忙信號)
寫指令38H
寫指令08H 關閉顯示
寫指令01H 顯示清屏
寫指令06H 光標移動設置
寫指令0cH 顯示開及光標設置
3.設置顯示地址(寫顯示字符的位置)。
4.寫顯示字符的數據。
三、LCD1602各子程序模塊及主程序編寫:
現在按照上面編寫程序的流程,給出各子程序模塊及主程序的例子。
1.頭文件,宏定義,定義管腳等:
#include《reg52.h》
#include 《string.h》
#define uchar unsigned char
#define uint unsigned int
sbit EN=P3^4;
sbit RS=P3^5;
sbit RW=P3^6;
uchar code table0[]={“QQ:545699636”
};
//此條語句為顯示字符串時定義的字符串數組
2.LCD1602基本初始化子程序:
void LCD1602()
{
EN=0;
RS=1;
RW=1;
P0=0xff;
//這里P0為與LCD D0~D7相連的I/O口
}
3.讀忙子程序:
void read_busy()
{
P0=0xff;
RS=0;
RW=1;
EN=1;
while(P00x80);
//P0和10000000相與,D7位若不為0,停在此處
EN=0;
//若為0跳出進入下一步;這條語句的作用就是檢測
}
//D7位,若忙在此等待,不忙跳出讀忙子程序執(zhí)行讀寫指令
4.寫指令寫數據子程序:
void write(uchar i,bit j)
{
read_busy();
P0=i;
//其中i=0,寫指令;i=1,寫數據;
RS=j;
RW=0;
EN=1;
EN=0;
}
5.延時子程序:
void delay(uint c)
//功能為提供初始化等其他子程序中的延時1xc MS
{
uint a,b;
for(a=0;a《c;a++)
for(b=0;b《120;b++);
}
6.LCD1602初始化子程序:
void init()
//完全按照要求初始化流程來,中間省略了一步寫指令38H
{
delay(15);
write(0x38,0);
delay(5);
write(0x38,0);
write(0x08,0);
write(0x01,0);
write(0x06,0);
write(0x0c,0);
}
7.顯示單個字符子程序:
void display_lcd_byte(uchar y,uchar x,uchar z)
//Y=0,1(起始行),
{
// X=0~15(起始列),Z=想寫入字符的ASCII碼
if(y)
//是否顯示在第二行(若在第一行Y=0,不進入IF語句,若在第
{
//二行,進入IF語句
x+=0x40;
//第二行起始地址加上列數為字符顯示地址
}
x+=0x80;
//設置數據指針位置
write(x,0);
write(z,1);
//寫入數據
}
8.顯示字符串子程序:
void display_lcd_text(uchar y,uchar x,uchar table[])
{
//Y(起始行),X(起始列)同字符顯示,table[]字符串數組
uchar z=0;
uchar t;
t=strlen(table)+x;
//
求得字符串長度加上起始列位置
while(x《t)
//功能為LCD顯示到字符串最后一個字符,防止字符串
{
//沒有16個字符,從而不夠位產生亂碼;
display_lcd_byte(y,x,table[z]);
//逐位顯示數組內字符
x++;
z++;
}
}
9.主程序:
主程序里除了放入初始化程序外就是加入自己編寫的顯示子程序,根據你所要的不用功能可以編寫各種類型的顯示子程序,這里不做詳細介紹,以下舉例為顯示一個字符和顯示字符串的顯示子程序。
void main()
{
LCD1602();
init();
display_lcd_byte(0,0,‘A’);
//
顯示一個字符
display_lcd_text(1,3,table);
//
顯示字符串
while(1);
}
到此,讓LCD1602顯示的操作流程和編程思想基本可以告一段落了,但是1602的功能實現遠不止這些。利用1602你可以做出動態(tài)效果的顯示,并且除了顯示一般字符外,1602還支持自定義字符等等其他一些功能,下面在最后簡單介紹下顯示動態(tài)效果和自定義字符。
一、顯示動態(tài)效果:
顯示動態(tài)效果包括讓一個字符或字符串原位置閃爍,或者前后移動等等。其實動態(tài)效果原理很簡單,就是簡單的利用延時。
例如讓字符原位置閃爍,可以認為是先讓1602顯示字符,延時一段時間后,可以顯示空格或者直接清屏操作都可以達到讓字符消失不見的效果,再延時一段時間后再讓1602顯示這個字符。
同理,讓字符前后移動也是這樣,例如讓字符在第一個位置顯示,延時一段時間后讓其在后面第二個位置顯示,只要顯示地址加1,然后顯示即可。字符串也是同樣的道理。
在這里補充一點就是如何讓字符串從1602第16個地址外進入,動態(tài)向前移動。其實可以通過顯示地址表我們知道起始位置開始后1602一行只能顯示16個字符,但是一行的地址卻遠遠不止16個。大家可以看到第一行顯示地址是從00~27,然而能顯示在1602可見范圍的只有00~0F,后面的位置其實就是起到一個緩沖的作用,你完全可以讓字符數據存在在10地址后的RAM中,只不過,我們無法看到就是了,如果存在10前的地址我們就能看到顯示。
因此,我們可以先把顯示起始地址設在10地址后的某一個位置,然后讓字符顯示地址每次加1,當加到0F時,我們就可以看到字符串第一個字符出現在1602的最末一位,然后繼續(xù)向前移動。
下面給出一段字符串移動顯示的例子:
void display_lcd_byte(uchar y,uchar x,uchar z)
{
if(y)
{
x+=0x40;
}
x+=0x80;
write(x,0);
write(z,1);
}
void display_lcd_text(uchar y,uchar x,uchar table[])
{
uchar z=0;
uchar t;
t=strlen(table)+x;
while(x《t)
{
display_lcd_byte(y,x,table[z]);
x++;
z++;
}
display_lcd_byte(y,x,‘ ’);
}
//前兩個子程序是顯示子程序
void main()
{
uchar i;
LCD1602();
init();
for(i=16;i》=0;i--)
//這里的循環(huán)就是為了字符串從后往前顯示
{
display_lcd_text(0,i,table0);
//i減一次,首個字符就往前去一位
delay(200);
}
while(1);
}
二、顯示自定義字符:
要想顯示自定義字符,首先就得取得想要的圖形或者字符的字模數組,可以通過手動提取的方法,取得相應的字模。
如圖所示,對應一個字符顯示區(qū)域。每8個字節(jié),組成一個點陣數組。
要想讓某一格子顯示就讓那一位為1,每行自定義5位,全白為0x00;全黑為0x1f。一共8行,每行一位數據。
將生成的點陣數組保存到CGRAM存儲器中,生成自定義字符。1602內部CGRAM用于自定義的字符點陣的存儲,總共64字節(jié)。由上一步點陣提取可知,每一個字符由8個字節(jié)數據組成。所以64字節(jié)CGRAM存儲器,能夠存儲8組自定義字符的點陣數組。按照CGRAM地址劃分為 0~7為第一組,8~15為第二組,依次類推56~63為第8組數據。
CHARACTER CODE是數據的顯示地址,0-7的范圍,能存儲8位自定義的字符。(能存八個自定義,每個字符存放的)
CGRAM ADDRESS是存儲數據的地址,從0-63共64個字節(jié)。存儲64個數據。我們寫入的數據是0x40~0x7F,共128位。(把字符數組內的8個數送進這8個地址,每存完一個字符的8位,下次地址直接轉到0x48)
CGRAM DATA 字模每一行5位數據存
內部常用字符顯示時,顯示編碼是從0x20開始的。0x00~0x0F是專門留給自定義字符顯示的。0x00~0x07和0x08~0x0F內容是一樣的。例如:調用0x01 位置和0x09位置,顯示的內容是一樣的。
LCD1602自定義顯示字符的方式共四步,如下面所示:
1.設置向CGRAM中存入這個數據。初始地址是0x40。然后存一位向后加8,
總共能存8位自定義的字符。
2.然后可以把自定義的數據送入到LCD的CGRAM中。
3.向LCD寫指令,送入需要顯示數據的地址。
4.向LCD寫指令,把顯示的數據指向LCD的CGRAM存儲的位置,顯示出自定義字符。
舉例如下:
1.建立一個字符數組;
uchar LCD_Data1[]={0x01,0x03,0x1D,0x11,0x1D,0x03,0x01,0x00};
2.設置CGRAM地址,寫指令;
Write_LCD(0x40,0);
3.把數據送入CGRAM地址內;
for(i = 0; i 《 8 ; i ++ )
{
Write_LCD(LCD_Data1,1);
}
4.寫需要顯示的位置指令;
Write_LCD(0x80,0);
5.把CGRAM的0位的數據送向LCD1602,顯示數據存儲的數據;
Write_LCD(0x00,1);
評論