一、LCD12864液晶的工作原理
液晶顯示屏中的業(yè)態(tài)光電顯示材料,利用液晶的電光效應(yīng)把電信號(hào)轉(zhuǎn)換成數(shù)字符、圖像等可見(jiàn)信號(hào)。
如圖1-1,液晶正常情況下,其分子排列很有秩序,顯得清澈透明,一旦加上直流電場(chǎng)后,分子的排列被打亂,一部分液晶變的不透明,顏色加深因而能顯示數(shù)字和圖像。管腳一共1個(gè)CS1左半屏片選端,CS2右半屏片選端;V0液晶顯示驅(qū)動(dòng)電壓,通過(guò)一個(gè)電位器接到VCC;RS數(shù)據(jù)指令選擇信號(hào),H為數(shù)據(jù),L為指令,也叫D/I;R/W讀寫選擇信號(hào),H為讀,L為寫,。E為L(zhǎng)CD使能端,R/W為L(zhǎng)時(shí),E信號(hào)下降沿鎖存 DB7-DB0;R/W為H時(shí),E為H,DDRAM數(shù)據(jù)讀到DB7-DB0。DB0-DB7數(shù)據(jù)傳輸端口。RST復(fù)位信號(hào)。-VOUT 和V0為液晶顯示驅(qū)動(dòng)電壓。 12864是一種圖形點(diǎn)陣液晶顯示器,它主要由行驅(qū)動(dòng)器/列驅(qū)動(dòng)器及128×64 全點(diǎn)陣液晶顯示器組成。可完成圖形顯示,也可以顯示8×4個(gè)(16×16點(diǎn)陣)漢字。?
圖1-1 12864LCD液晶顯示屏
二、方案設(shè)計(jì)
2.1 實(shí)物硬件設(shè)計(jì)
單片機(jī)控制液晶顯示屏系統(tǒng)總共可分為六個(gè)環(huán)節(jié),分別是單片機(jī)控制系統(tǒng)、12864字符顯示模塊、控制開關(guān)模塊、晶振控制模塊、復(fù)位電路模塊和DS1302時(shí)鐘控制模塊。通過(guò)這六個(gè)模塊的協(xié)調(diào)工作就可以完成相應(yīng)的液晶屏控制和顯示功能。這六個(gè)模塊的相互連接如圖2-1:
圖2-1 硬件組成框圖
2.2 系統(tǒng)硬件設(shè)計(jì)
本硬件電路主要由四大模塊組成:主芯片模塊;晶振和復(fù)位電路模塊;控制接鈕模塊;顯示電路
模塊。
2.2.1 主芯片模塊
主芯片模塊即單片機(jī)模塊,XTAL1:接外部晶振和微調(diào)電容的一端。在片內(nèi),它是振蕩電路反相放大器的輸入端。XTAL2:接外部晶振和微調(diào)是容的一端。RST:AT89C51的復(fù)位信號(hào)輸入引腳,高電平有效。當(dāng)此輸入端保持兩個(gè)機(jī)器周期的高電平時(shí),就可以完成復(fù)位操作。ALE:允許地址鎖存信號(hào)端。EA:該引腳為低電平時(shí),則讀取外部的程序代碼來(lái)執(zhí)行程序。P0、P1、P2、P3:8位并行輸入輸出口。每個(gè)端口都是8位準(zhǔn)雙向口,共占32只引腳。每一條都能獨(dú)立地用作輸入或輸出。每個(gè)端口都包括一個(gè)鎖存器、一個(gè)輸出驅(qū)器和輸入緩沖器。作輸出時(shí),數(shù)據(jù)可以鎖存;作輸入時(shí),數(shù)據(jù)可以緩沖。圖如圖3—1。
圖3-1 單片機(jī)引腳圖
2.2.2 晶振和復(fù)位模塊
89C51芯片內(nèi)部有一個(gè)高增益反相放大器,用于構(gòu)成振蕩器。如圖3—2,反相放大器的輸入端為XTAL1,輸出端XTAL2,兩個(gè)跨接石英晶體及兩個(gè)電容就可以構(gòu)成穩(wěn)定的自激振蕩器。XTAL1 是片內(nèi)振蕩器的反相放大器輸入端,XTAL2 則是輸出端,使用外部振蕩器時(shí),外部振蕩信號(hào)應(yīng)直接加到XTAL1,而XTAL2 懸空。一個(gè)晶體振蕩器,接在單片機(jī)內(nèi)部的振蕩電路上,兩個(gè)電容是起振電容,頻率越高,應(yīng)該越小。
圖4-1 晶振模塊
在振蕩器運(yùn)行時(shí),有兩個(gè)機(jī)器周期(24 個(gè)振蕩周期)以上的高電平出現(xiàn)在此引腳時(shí),將使單片機(jī)復(fù)位,只要這個(gè)腳保持高電平,51 芯片便循環(huán)復(fù)位。復(fù)位后P0-P3 口均置1 引腳表現(xiàn)為高電平,程序計(jì)數(shù)器和特殊功能寄存器SFR 全部清零。當(dāng)復(fù)位腳由高電平變?yōu)榈碗娖綍r(shí),芯片為ROM 的00H 處開始運(yùn)行程序。如上圖5-1所示復(fù)位電路,由于復(fù)位時(shí)高電平有效,當(dāng)剛接上電源的瞬間,電容C1兩端相當(dāng)于短路,即相當(dāng)于給RESET引腳一個(gè)高電平,等充電結(jié)束時(shí)(這個(gè)時(shí)間很短暫),電容相當(dāng)于斷開,這時(shí)已經(jīng)完成了復(fù)位動(dòng)作。
圖5-1 復(fù)位模塊
2.2.3 按鈕模塊
本模塊采用四個(gè)按鈕進(jìn)行控制,通過(guò)串行口輸入輸出連接,當(dāng)K1按鍵波動(dòng)一次后,方可進(jìn)行年、月、日、星期、時(shí)、分的改變,當(dāng)循環(huán)滿時(shí),按下K0可實(shí)現(xiàn)對(duì)鬧鐘的改變。按鍵K2、K3分別實(shí)現(xiàn)加一減一的操作。
圖6-1 按鈕模塊
2.3 系統(tǒng)軟件設(shè)計(jì)
2.3.1 主程序設(shè)計(jì)
圖7-1 主程序流程圖
圖8-1 LCD顯示程序和初始化子程序流程圖
三、仿真和分析
將程序下載到單片機(jī)開發(fā)板上,LCD12864顯示如下圖,第一行為漢字“數(shù)字電子鐘”,第二行為時(shí)分秒,第三行為年月日以及星期,第四行為鬧鐘,通過(guò)按鍵可實(shí)現(xiàn)時(shí)間的調(diào)整,也可實(shí)現(xiàn)整點(diǎn)報(bào)時(shí)和鬧鐘。符合設(shè)計(jì)要求。
圖9-1 實(shí)物仿真圖
程序:
#include《reg52.h》
{ uchar i,j; for(i=xms;i》0;i--)
for(j=110;j》0;j--);
}
void warn(uchar xn)//“嘟”xn次函數(shù) { uint nn;
for(nn=0;nn《xn;nn++) { uint n;
for(n=2000;n》0;n--) { beep=1; delayms(1); beep=0; delayms(2);
}
for(n=1000;n》0;n--) { beep=1;
delayms(3);
}
}
}
void warn3s()//3s報(bào)警函數(shù) { uint n;
for(n=3000;n》0;n--) { beep=0; delayms(2); beep=1; delayms(1);
}
}
void write_com(uchar com)//12864寫指令函數(shù) { rs=0; rw=0; en=0; P2=com; delayms(5); en=1; delayms(5); en=0; }
void write_data(uchar date)//12864數(shù)據(jù)指令函數(shù) { rs=1; rw=0; en=0; P2=date; delayms(5); en=1; delayms(5); en=0;
}
{ X=0x88;
} if(X==3) { X=0x98; } pos=X+Y; write_com(pos);
}
void write_sfm(int add,uint date)//時(shí)鐘數(shù)值函數(shù) { uchar shi,ge; shi=date/10; ge=date%10; lcd_pos(1,0+add); write_data(0x30+shi); write_data(0x30+ge);
}
void write_sfm1(int add1,uint date1)//年月日數(shù)值函數(shù) { uchar shi,ge;
shi=date1/10;
void lcd_pos(uchar X,uchar Y)//12864顯示位置函數(shù) { uchar pos; if(X==0) { X=0x80; } if(X==1) { X=0x90; }
if(X==2)
{ X=0x88;
} if(X==3) { X=0x98; } pos=X+Y; write_com(pos);
}
void write_sfm(int add,uint date)//時(shí)鐘數(shù)值函數(shù) { uchar shi,ge; shi=date/10; ge=date%10; lcd_pos(1,0+add); write_data(0x30+shi); write_data(0x30+ge);
}
void write_sfm1(int add1,uint date1)//年月日數(shù)值函數(shù) { uchar shi,ge;
shi=date1/10;
ge=date1%10; lcd_pos(2,0+add1); write_data(0x30+shi); write_data(0x30+ge);
}
void write_sfm2(int add2,uint date2)//鬧鐘數(shù)值函數(shù) { uchar shi,ge; shi=date2/10; ge=date2%10; lcd_pos(3,0+add2); write_data(0x30+shi); write_data(0x30+ge);
}
{ TR0=0;
write_com(0x0f); lcd_pos(3,2);
}
}
if(kk==2) { lcd_pos(3,4);
} if(kk==3) { lcd_pos(3,6); } if(kk==4) { kk=0; TR0=1;
write_com(0x0c);
}
}
if(k1==0)//調(diào)試按鍵操作 { delayms(5);
if(k1==0)
void keyscan()//按鍵掃描函數(shù) { if(k0==0)//鬧鐘按鍵操作 { delayms(5); if(k0==0) { while(!k0); kk++;
if(kk==1)
{ k++; while(!k1); if(k==1) { TR0=0;
write_com(0x0f); lcd_pos(1,4);
}
} if(k==2) { lcd_pos(1,2); } if(k==3) { lcd_pos(1,0); } if(k==4) { lcd_pos(2,4); } if(k==5) {
lcd_pos(2,2);
} if(k==6) { lcd_pos(2,0);
} if(k==7) { lcd_pos(2,7); } if(k==8) { k=0;
write_com(0x0c);
TR0=1;
}
}
if(k!=0) { if(k2==0)//“+1”按鍵操作 { delayms(5); if(k2==0) { while(!k2);
if(k==1)
{ miao++; if(miao==60)
miao=0;
write_sfm(4,miao);
lcd_pos(1,4); // write_sfm(4,miao);
} if(k==2) { fen++; if(fen==60)
fen=0; write_sfm(2,fen);
lcd_pos(1,2); // write_sfm(2,fen);
} if(k==3) { shi++; if(shi==24)
shi=0; write_sfm(0,shi);
lcd_pos(1,0); //
write_sfm(0,shi);
} if(k==4) { ri++; if(ri==32)
ri=1;
write_sfm1(4,ri);
lcd_pos(2,4); // write_sfm1(4,ri);
} if(k==5) { yue++; if(yue==13)
yue=1; write_sfm1(2,yue);
lcd_pos(2,2); // write_sfm1(2,yue);
} if(k==6) { nian++; if(nian==50)
nian=0;
write_sfm1(0,nian);
lcd_pos(2,0); // write_sfm1(0,nian);
}
if(k==7) { zhou++; if(zhou==8)
zhou=0;
write_sfm1(7,zhou);
lcd_pos(2,7); // write_sfm1(7,zhou);
}
}
}
if(k3==0)//“-1按鍵操作” { delayms(5); if(k3==0) { while(!k3); if(k==1) { miao--; if(miao==-1)
miao=59;
write_sfm(4,miao);
lcd_pos(1,4); // write_sfm(4,miao);
}
if(k==2) { fen--; if(fen==-1)
fen=59;
write_sfm(2,fen);
lcd_pos(1,2); // write_sfm(2,fen);
} if(k==3) { shi--; if(shi==-1)
shi=23; write_sfm(0,shi);
lcd_pos(1,0); // write_sfm(0,shi);
} if(k==4) {
ri--;
if(ri==-1)
ri=31;
write_sfm1(4,ri);
lcd_pos(2,4); // write_sfm1(4,ri);
}
if(k==5) { yue--; if(yue==-1)
yue=12;
write_sfm1(2,yue);
lcd_pos(2,2); // write_sfm1(2,yue);
} if(k==6) { nian--; if(nian==-1)
nian=50; write_sfm1(0,nian);
lcd_pos(2,0); // write_sfm1(0,nian);
}
if(k==7)
{ zhou--; if(zhou==-1)
zhou=7;
write_sfm1(7,zhou);
lcd_pos(2,7); // write_sfm1(7,zhou);
}
}
}
}
if(k==0) { if(k2==0) { delayms(5); if(k2==0) { while(!k2); if(kk==3) { miao0++; if(miao0==60)
miao0=0;
write_sfm2(6,miao0);
lcd_pos(3,6); // write_sfm2(6,miao0);
}
if(kk==2) { fen0++; if(fen0==60)
fen0=0;
write_sfm2(4,fen0);
lcd_pos(3,4); // write_sfm2(4,fen0);
} if(kk==1) { shi0++; if(shi0==24)
shi0=0; write_sfm2(2,shi0);
lcd_pos(3,2); // write_sfm2(2,shi0);
}
}
}
if(k3==0)
{
delayms(5); if(k3==0) { while(!k3); if(kk==3) { miao0--; if(miao0==-1)
miao0=59;
write_sfm2(6,miao0);
lcd_pos(3,6); // write_sfm2(6,miao0);
} if(kk==2) { fen0--; if(fen0==-1)
fen0=59; write_sfm2(4,fen0);
lcd_pos(3,4); // write_sfm2(4,fen0);
} if(kk==1) {
shi0--;
if(shi0==-1)
shi0=23;
write_sfm2(2,shi0);
lcd_pos(3,2); // write_sfm2(2,shi0);
}
}
}
}
}
void init()//初始化函數(shù)(12864初始化,定時(shí)器初始化) { PSB=1;
write_com(0x30); delayms(5); write_com(0x0c); delayms(5); write_com(0x01); delayms(5);
TH0=(65535-50000)/256; TL0=(65535-50000)%256; TMOD=0x01; ET0=1;
EA=1;
TR0=1;
}
void main()//主函數(shù) { uchar i; delayms(10); init();
lcd_pos(0,2);//第一排顯示 i=0;
while(dis1[i]!=‘