?LCD1602的顯示原理
學單片機的小朋友應該都見過這個顯示器--LCD1602,這是最古老最簡單的顯示屏,上世紀80年代的產物。
它顯示的圖案如下所示
顯示部分放大就是下面這樣 ,像素就是一個個小方塊,相當于描點法繪圖了。
如果把所有像素全部顯示出來就是下面這樣,全部是小黑點
?全部點亮的像素點如下所示,16列,2行,這就是1602名字的來歷
每個顯示區(qū)域又可以細分為35個像素,7行5列
?整個屏幕就是35*16*2 = 1120個像素
要想搞清楚這1120個像素的控制,就得先明白一個像素是這么控制的。顯示屏的最下面是一層LED背光板,
只要通上電就會發(fā)光
在背光板上鋪上一層液晶,每一小塊的液晶就可以控制一個像素點
當不給液晶施加電壓,液晶就是透明的,給某一塊液晶施加電壓后,就不透光了,看到的就是一個小黑點,常見的LCD背光有白光、藍光、綠光,所以大家一般看到的要么是黑點,要么是背光。控制像素點就是控制他所對應的液晶的電壓高低。
數碼管只有8段,8個IO口就夠了,可以用單片機直接控制,但是LCD1602有1120個像素點,1120個引腳的單片機我還沒遇到,怎么辦?這時候顯示芯片HD44780U可以出場了。44780有80個引腳
單片機把想要顯示的東西發(fā)給HD44780U,HD44780U再來控制顯示屏就可以
所以這個HD44780U就有點像電腦的顯卡了。
LCD1602液晶屏的背面長這個樣子,首先映入眼簾的就是那兩個大黑點,大黑點里面封裝的就是芯片,大的那個是HD44780U,小一點的那個黑點是HD44100H,他的作用后面會講到。關于芯片的封裝,大家可能都覺得芯片 就應該是哪種方形的,有引腳的哪種,其實還有一種COB的封裝,就像狗皮膏藥一樣黏在PCB上,這種封裝便宜啊。
LCD1602一共有16個引腳,其中數據引腳又8個,控制這8個引腳的數據,就能控制液晶屏的顯示內容。因為每個顯示區(qū)域就35個像素,描點法也只能描出簡單的圖案,比如數字,字面,符號等。
比如大些字母A,ASCII碼表是0100 0001,對應的數據引腳電平就是:
0???????? 1???????? 0 ????????0 ????????0????????0????????0????????1
低 ??????高 ??????低 ???????低 ?????低???????低??????低 ???????高
但是這個A在哪個區(qū)域顯示呢?HD44780U里面給每個顯示區(qū)域都規(guī)定的地址,這個地址就存在芯片內部的DRAM里面,
?
??這個DRAM就相當于顯卡的顯存了,只是大小只有80個字節(jié),可以同時控制80個字符
?
LCD1602最多也就能顯示32個字符,HD44780U為什么能控制80個字符,因為他是通用的芯片,不是為LCD1602定制的,多的部分可以空著不用。
?后面的紅色部分就是多余的地址,控制不用
?先發(fā)送顯存的地址,再發(fā)送需要顯示的內容,這樣數據就會被保存在相應的顯存里面
比如讓液晶屏的第一塊顯示區(qū)域顯示大些字母A,就先發(fā)送第一塊顯示區(qū)域的地址0x00,再發(fā)送A的ASCII碼0100 0001,怎么顯示那就是顯示芯片HD44780U的事情了。
HD44780U的芯片管腳分布如下那些SEG和COM引腳就是控制引腳,是不是似曾相識,數碼管的SEG引腳和COM引腳,原理可以說是差不多的。
?COM引腳控制行,SEG引腳控制列,如果要顯示A,那就是在相應的交叉點輸出不同的電壓就行了
因為不能同時控制所有行列的電壓,只能用掃描的方式,一行一行的控制,是不是也似曾相識,多為數碼管的動態(tài)顯示也是這樣的。
掃描第一行,并輸出對應的電壓?
掃描第二行并輸出對應的電壓
掃描第三行并輸出對應的電壓
掃描第四行并輸出對應的電壓?
掃描第五行并輸出對應的電壓?
掃描第六行,并輸出對應的電壓
掃描第七行并輸出對應的電壓?
掃描快一點,根根人眼的視覺殘留,就能看到完整的A了
?HD44780U的SEG引腳只有40個,5個SEG腳才能控制一列顯示區(qū),40個SEG腳一共也只能控制8列顯示區(qū)啊,LCD1602可是有16列顯示區(qū)的,那另外的8列的顯示區(qū)怎么控制,而且前面也說了,HD44780U能控制80個字符,現在怎么才16個。對HD44780U的顯存DRAM是可以控制80個字符,但是引腳不夠啊,這個時候該HD44100H出場了。
HD44100H就是那個小一點的黑點
它正好也有40個SEG引腳
?將HD44780U和HD44100H拼在一起不就好了
?加4個HD44100H,換一個能顯示80個字符的液晶顯示屏,就能顯示80個字符了,HD44780U里面的DRAM就只有80個地址,只能顯示80個字符。
LCD1602相關的寄存器以及電路
?1、認識LCD
LCD == Liquid Crystal Display ==液晶顯示器
LCD1602表示一種液晶屏,能同時顯示2行16列,共32個字符,這個字符可以是字母,數字,符號等
LCD結構上主要由3部分組成:
液晶:液態(tài)晶體,液晶本身不發(fā)光,但他在通電的時候可以讓光線透過去,不通電時光線透不過去;
光源:這個光源才是點亮LCD的關鍵;
偏光片:又上下兩片,液晶就在上下偏光片之間,改變偏光片的角度就可以讓光線在特定的地方透過
上下兩片偏光片有點像兩個石子交叉的百葉窗,自己去腦補一下。
2、LCD1602的管腳以及管腳功能
管腳序號 |
管腳符號 |
管腳說明 |
1 |
VSS |
電源地, |
2 |
VDD |
電源正極,是LCD1602驅動系統(tǒng)的電源 |
3 |
VO |
液晶顯示對比度調整管腳,接正電源是對比度最低,接地時對比度最高,但是對比度太高,就容易看到一些不該看到的東西,俗稱“鬼影”,一般在這個腳通過電阻再接地。 |
4 |
RS |
Register Select的縮寫,字面意思就是寄存器選擇;當RS=1的時候,通訊的是數據;當RS=0的時候,通訊的是命令。 |
5 |
R/W |
讀,寫選擇,當R/W = 1的時候表示讀LCD里面的數據,R/W = 0的時候表示往LCD里面寫數據。 |
6 |
E |
使能信號,當E=1的時候讀取信息,當E由1變?yōu)?的時候,液晶模塊開始執(zhí)行命令;要配合控制時序來用。 |
7 |
D0 |
數據第0位,D0--D7是雙向的數據線,對LCD模塊進行讀寫。 |
8 |
D1 |
數據第1位 |
9 |
D2 |
數據第2位 |
10 |
D3 |
數據第3位 |
11 |
D4 |
數據第4位 |
12 |
D5 |
數據第5位 |
13 |
D6 |
數據第6位 |
14 |
D7 |
數據第7位 |
15 |
BLA |
背光源正極,可以理解為那個背光LED的正極電源,可以直接接VDD |
16 |
BLK |
背光源負極,可以理解為那個背光LED的負極電源,可以直接接VSS |
3、LCD1602 的RAM地址映射
LCD1602能同時顯示2行16列,一共32個位置,每個位置都對應著一個地址,每個地址里面可以促一個字節(jié)的字符,需要在哪個位置顯示某種字符,就在他對應的地址上寫入某種字符。
下圖就是這32個顯示位置所對應的地址,這個地址也就是DDRAM地址;
其實LCD1602的DDRAM一共有80個地址,依然是兩行,每行40個地址,但是LCD1602一行只能同時顯示16個地址的數據,剩下的24個在后面隱藏著。怎么辦,只能用光標移動的方法把隱藏的部分顯示出來。
4、LCD1602的顯示設置
比如你想在第1行,第3列的位置顯示個字符A,該怎么處理?
首先確定位置,第1行第3列的地址是02,轉換為2進制就是0000 0010,但是LCD1602有自己的規(guī)矩,就是寫地址的時候,最高位必須是1,也就是說寫進LCD的地址應該為1000 0010。
然后確定字符,LCD1602模塊里面有個字符產生器,簡稱CGROM(Character Generator ROM)里面存著一些常用的字模,你只需要根據地址來查詢就可以了,比如字符A的地址就是0x41。
5、LCD1602的命令列表
6、單片機控制LCD1602電路
?
LCD1602液晶靜態(tài)顯示
程序實例1:
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include<intrins.h>
sbit RS = P2^4; //定義端口
sbit RW = P2^5;
sbit EN = P2^6;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函數
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
寫入命令函數
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙則等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入數據函數
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙則等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函數
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
寫入字符串函數
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
寫入字符函數
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函數
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*顯示模式設置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示光標移動設置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及光標設置*/
}
/*------------------------------------------------
主函數
------------------------------------------------*/
void main(void)
{
LCD_Init();
LCD_Clear();//清屏
while (1)
{
LCD_Write_Char(7,0,'o');
LCD_Write_Char(8,0,'k');
LCD_Write_String(1,1,"hello world!");
while(1);
}
}
LCD1602液晶動態(tài)顯示
程序實例2:
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include<intrins.h>
sbit RS = P2^4; //定義端口
sbit RW = P2^5;
sbit EN = P2^6;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函數
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
寫入命令函數
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙則等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入數據函數
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙則等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函數
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
寫入字符串函數
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
寫入字符函數
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函數
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*顯示模式設置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示光標移動設置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及光標設置*/
}
/*------------------------------------------------
主函數
------------------------------------------------*/
void main(void)
{
unsigned char i;
unsigned char *p;
LCD_Init();
while (1)
{
i = 1;
p = "hello world!";
LCD_Clear();
LCD_Write_String(2,0,"Welcome to");
DelayMs(250);
while (*p)
{
LCD_Write_Char(i,1,*p);
i ++;
p ++;
DelayMs(250);
}
DelayMs(250);
}
}
LCD1602液晶滾動顯示
程序實例3:
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include<intrins.h>
sbit RS = P2^4; //定義端口
sbit RW = P2^5;
sbit EN = P2^6;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函數
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
寫入命令函數
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙則等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入數據函數
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙則等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函數
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
寫入字符串函數
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
寫入字符函數
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函數
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*顯示模式設置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示光標移動設置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及光標設置*/
}
/*------------------------------------------------
主函數
------------------------------------------------*/
void main(void)
{
LCD_Init();
LCD_Clear();//清屏
LCD_Write_Char(7,0,'o');
LCD_Write_Char(8,0,'k');
LCD_Write_String(1,1,"hello world!");
while (1)
{
DelayMs(200);
LCD_Write_Com(0x18);//左平移畫面 0x1C 是右平移
}
}
LCD1602移動顯示
程序實例4:文章來源:http://www.zghlxwxcb.cn/news/detail-707896.html
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include<intrins.h>
sbit RS = P2^4; //定義端口
sbit RW = P2^5;
sbit EN = P2^6;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函數
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
寫入命令函數
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙則等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入數據函數
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙則等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函數
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
寫入字符串函數
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
寫入字符函數
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函數
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*顯示模式設置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示光標移動設置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及光標設置*/
}
/*------------------------------------------------
主函數
------------------------------------------------*/
void main(void)
{
unsigned char i;
unsigned char *pa,*pb;
LCD_Init();
LCD_Write_Com(0x0f);//光標開,光標閃爍開
while (1)
{
pa = "Welcome to";
pb = "hello world!";
LCD_Clear();
LCD_Write_String(2,0,pa); //顯示2行信息
LCD_Write_String(1,1,pb);
for(i=0;i<8;i++) //延時2s左右
DelayMs(250);
LCD_Clear(); //清屏顯示其他信息
i = 2;
while (*pa) //循環(huán)輸入方式顯示2行信息
{
LCD_Write_Char(i,0,*pa);
i ++;
pa ++;
DelayMs(250);
}
i=1;
while (*pb)
{
LCD_Write_Char(i,1,*pb);
i ++;
pb ++;
DelayMs(250);
}
DelayMs(250);
}
}
LCD1602液晶按鍵輸入顯示
程序實例5:文章來源地址http://www.zghlxwxcb.cn/news/detail-707896.html
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
#include<intrins.h>
sbit RS = P2^4; //定義端口
sbit RW = P2^5;
sbit EN = P2^6;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
#define KeyPort P1
unsigned char code show_code[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};//轉換成液晶顯示的字符
/*------------------------------------------------
uS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
長度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延時函數,含有輸入參數 unsigned char t,無返回值
unsigned char 是定義無符號字符變量,其值的范圍是
0~255 這里使用晶振12M,精確延時請使用匯編
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延時1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函數
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
寫入命令函數
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙則等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
寫入數據函數
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙則等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函數
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
寫入字符串函數
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
寫入字符函數
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函數
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*顯示模式設置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*顯示關閉*/
LCD_Write_Com(0x01); /*顯示清屏*/
LCD_Write_Com(0x06); /*顯示光標移動設置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*顯示開及光標設置*/
}
/*------------------------------------------------
按鍵掃描函數,返回掃描鍵值
------------------------------------------------*/
unsigned char KeyScan(void) //鍵盤掃描函數,使用行列反轉掃描法
{
unsigned char cord_h,cord_l;//行列值中間變量
KeyPort=0x0f; //行線輸出全為0
cord_h=KeyPort&0x0f; //讀入列線值
if(cord_h!=0x0f) //先檢測有無按鍵按下
{
DelayMs(10); //去抖
if((KeyPort&0x0f)!=0x0f)
{
cord_h=KeyPort&0x0f; //讀入列線值
KeyPort=cord_h|0xf0; //輸出當前列線值
cord_l=KeyPort&0xf0; //讀入行線值
while((KeyPort&0xf0)!=0xf0);//等待松開并輸出
return(cord_h+cord_l);//鍵盤最后組合碼值
}
}
return(0xff); //返回該值
}
/*------------------------------------------------
按鍵值處理函數,返回掃鍵值
------------------------------------------------*/
unsigned char KeyPro(void)
{
switch(KeyScan())
{
case 0x7e:return 0;break;//0 按下相應的鍵顯示相對應的碼值
case 0x7d:return 1;break;//1
case 0x7b:return 2;break;//2
case 0x77:return 3;break;//3
case 0xbe:return 4;break;//4
case 0xbd:return 5;break;//5
case 0xbb:return 6;break;//6
case 0xb7:return 7;break;//7
case 0xde:return 8;break;//8
case 0xdd:return 9;break;//9
case 0xdb:return 10;break;//a
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
/*------------------------------------------------
主函數
------------------------------------------------*/
void main(void)
{
unsigned char i,j,num;
LCD_Init();
LCD_Write_Com(0x0F);//光標開,光標閃爍開
LCD_Write_String(0,0,"Press the key !");
while (1)
{
num=KeyPro();
if(num!=0xff)
{
if((i==0)&&(j==0))//回到第一個字符時清屏
LCD_Clear();//清屏
LCD_Write_Char(0+i,0+j,show_code[num]);//依次顯示輸入字符
i++;
if(i==16)//如果第一行顯示滿,轉到第二行
{
i=0;j++;
if(j==2)//如果2行都顯示滿,清屏后重新從第一行顯示
{
j=0;
}
}
}
}
}
到了這里,關于單片機C語言實例:18、LCD1602液晶顯示的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!