在AT89C51的控制下,利用LCD1602和兩隻按鍵完成兩屏顯示的切換顯示:第一屏為自己姓名的拼音,第二位自為子學號;第二屏顯示:第一行為自己的籍貫,第二行為自己的生日。顯示利用LCd命令1——8進行設定,要求至少使用4個命令。
選擇P0口作為資料口;首先將姓名學號籍貫等資料存放在微控制器的程式儲存器內。再通過微控制器與LCD1206以資料匯流排的形式相連通過R/W,E控制訊號,D0~D7資料或命令訊號,加上獨立鍵盤掃描來控制顯示第一屏還是第二屏顯示;
以P0為資料和命令埠,P2^0~P2^2為控制訊號埠
LCD1206的命令字特點:
編號 | 命令 | Rs | R / W ‾ R/ \overline{W} R/W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 清屏 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | 遊標返回 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | × \times × |
3 | 顯示模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S |
4 | 顯示開關、遊標設定 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B |
5 | 遊標及字元移位 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | × \times × | × \times × |
6 | 功能設定 | 0 | 0 | 0 | 0 | 1 | DL | N | F | × \times × | × \times × |
7 | CGRAM地址 | 0 | 0 | 0 | 1 | 字 | 符 | 庫 | 地 | 址 | |
8 | DDRAm地址 | 0 | 0 | 1 | 數 | 據 | R | A | M | 第 | 址 |
9 | 讀忙標誌或地址 | 0 | 1 | BF | |||||||
10 | 寫資料 | 1 | 0 | ||||||||
11 | 讀資料 | 1 | 1 |
命令1 : 遊標返回00H(左上角位置)
命令2: 遊標返回
命令3:顯示設定
I/D: (1)地址指標加一;(0)地址指標減一
S: (1)寫入字元,整屏左移或右移 ;(0)整屏顯示不移動
命令4:D——螢幕顯示:1 開顯示;0關顯示
C——遊標有無:1 有; 0 無遊標
B——遊標閃爍:1閃爍;0 不閃爍
命令5 :SC =0 移動遊標 SC =1 移動顯示的字元
RL = 0 左移RL =1 右移
命令6: DL :1 八位資料 0 四位資料介面
N:1 兩行顯示 0 單行顯示
F: (1)5
×
10
\times10
×10陣 (0)5
×
7
\times7
×7 點陣
命令7:GGRAM地址設定,設定使用者自定義的字元
命令8:設定顯示地址:80H + 顯示位置
命令9: 讀忙: BF =1 忙;
命令10:寫資料
命令10: 讀資料
控制操作:
操作 | 微控制器發給LCD的控制訊號 | LCD的輸出 |
---|---|---|
讀狀態 | RS=0, R/ W ‾ \overline W W=1,E= 1 | D0~D7狀態 |
寫命令 | RS=0,R/ W ‾ \overline W W=0, D0~D7命令,E正脈衝 | 無 |
讀資料 | RS =1,R/ W ‾ \overline W W=1,E =1 | D0~D7資料 |
寫資料 | RS =1,R/ W ‾ \overline W W=0,D0~D7 資料,E正脈衝 | 無 |
#include<reg51.h>
#include<intrins.h>
#define out P0 //資料和命令埠
#define uchar unsigned char//預定義
#define uint unsigned int
sbit S1 =P1^0; // 按鍵1
sbit S2 =P1^1;//按鍵2
uchar keyvalue; // 鍵值
uchar code name[] ="Tang jie";//預存顯示資料
uchar code stu_num[] ="180844072";
uchar code birthplace[] ="Tong Ling";
uchar code birthday[] = "2000/01/27";
sbit RS = P2^0; // 資料或指令控制線
sbit RW = P2^1; // 讀寫控制線
sbit E = P2^2; //使能控制線
void key_scan(void); //鍵盤掃描宣告
/*********************
延時函數
*********************/
void delay(uint j)
{
uchar i = 250;
for(;j>0;j--)
{
while (--i);
i= 249;
while(--i);
i=250;
}
}
/*********************
檢查忙函數,檢查LCD是否處於忙狀態
如果處於忙則持續檢查
*********************/
void check_busy(void)
{
uchar temp;
do{
temp =0xff; //
E = 0;
RS= 0; //
RW = 1;
E =1;
temp = out; //
}while(temp&0x80); // 如果 BF =0 則持續檢查
E = 0;
}
/*********************
寫命令函數
*********************/
void write_command(uchar com)
{
check_busy();// 首先檢查忙
E= 0;//預置0
RS =0;
RW =0; //按LCD寫命令控制訊號設定
out = com;
E =1; // 正脈衝
_nop_();//
E = 0; // 還原E
delay(1);
}
void write_data(uchar com) //寫資料函數
{
check_busy();
E=0; //預置0
RS= 1;
RW =0;//按LCD寫資料控制訊號設定
out = com;
E=1;// 正脈衝
_nop_();
E =0;
delay(1);
}
void lcd_initial(void) //LCD初始化函數
{
write_command(0x38); // 八位資料,雙列顯示,5X7陣
_nop_();
write_command(0x0c); //開顯示屏,關遊標,遊標不顯示
_nop_();
write_command(0x06); //字元不移動,每次字元地址加1
_nop_();
write_command(0x01); //清屏
_nop_();
delay(100);
}
void string(uchar add, uchar *s)//字串顯函數
{
write_command(add);//顯示地址
while(*s != '\0')
{
write_data(*s++);
}
}
void key_1(void) // 第一屏顯示函數
{
lcd_initial();
string(0x80,stu_num); //第一行第一個開始顯示學號
string(0xc0,name);//第二行第一個開始顯示姓名
do{
key_scan();
} while(S2!=0);// 持續進行鍵盤掃描,如果按鍵2沒按下,則一直顯示第一屏
}
void key_2(void)
{
lcd_initial();
string(0x80,birthplace);//第一行第一個開始顯示籍貫
string(0xc0,birthday);//第二行第一個開始顯示生日
do{
key_scan();
} while(S1!=0); //持續進行鍵盤掃描,如果按鍵1沒按下,則一直顯示第一屏
}
void key_scan(void) //獨立鍵盤掃描函數
{
P1 =0xff;
if((P1&0x0f)!=0x0f)
{
delay(10);
if(S1==0)
{
keyvalue =1;
delay(100);
}
if(S2 == 0)
{
keyvalue =2;
delay(100);
}
}
}
void main(void) //主函數
{
keyvalue =0;
while(1)
{
key_scan(); //按鍵掃描
switch(keyvalue) //按鍵值選擇顯示第幾屏資料
{
case 1 : key_1();delay(10);break;
case 2 : key_2();delay(10);break;
}
}
}
按下按鍵1,顯示第一屏資料,顯示良好
按下按鍵2,顯示第二屏資料,顯示良好