《單片機(jī)萬年歷實訓(xùn)報告.doc》由會員分享,可在線閱讀,更多相關(guān)《單片機(jī)萬年歷實訓(xùn)報告.doc(19頁珍藏版)》請在裝配圖網(wǎng)上搜索。
單片機(jī)萬年歷實訓(xùn)報告
系 部:電氣自動化系
班 級:13電信2班
姓 名:周祝福
指導(dǎo)老師:黃麗英、侯聰玲
實訓(xùn)時間:2015年1月19日~23日
用AT89C51與LCD1602設(shè)計
的可調(diào)式電子日歷時鐘
一、總體設(shè)計
1.1、設(shè)計目的
為鞏固所學(xué)的單片機(jī)知識,把所學(xué)理論運(yùn)用到實踐中,用LCD1602與AT89C51 設(shè)計可調(diào)式電子日歷時鐘。
1.2、設(shè)計要求
(1)顯示:年、月、日、時、分、秒和星期;
(2)設(shè)置年、月、日、時、分、秒和星期的初始狀態(tài);
(3)能夠用4個按鍵調(diào)整日歷時鐘的年、月、日、時、分、秒和星期 ;
完成可調(diào)式電子日歷時鐘的硬件和軟件的設(shè)計,包括單片機(jī)的相關(guān)內(nèi)容;日歷時鐘模塊的設(shè)計,液晶顯示模塊的設(shè)計,按鍵模塊的設(shè)計??刂瞥绦虻木帉懙取?
1.3、 系統(tǒng)基本方案選擇和論證
1.3.1、單片機(jī)芯片的選擇方案
方案一:
采用89C51芯片作為硬件核心,采用Flash ROM,內(nèi)部具有4KB ROM 存儲空間,能于3V的超低壓工作,而且與MCS-51系列單片機(jī)完全兼容。
方案二:
采用STC12C5A60S2系列單片機(jī)是宏晶科技生產(chǎn)的單時鐘/機(jī)器周期(1T)的單片機(jī),是高速/低功耗/超強(qiáng)抗干擾的新一代8051單片機(jī),指令代碼完全兼容傳統(tǒng)8051,但速度快8-12倍。內(nèi)部集成MAX810專用復(fù)位電路,2路PWM,8路高速10位A/D轉(zhuǎn)換(250K/S),針對電機(jī)控制,強(qiáng)干擾場合。但造價較高。
1.3.2 、顯示模塊選擇方案和論證:
方案一:
采用點陣式數(shù)碼管顯示,點陣式數(shù)碼管是由八行八列的發(fā)光二極管組成,對于顯示文字比較適合,如采用顯示數(shù)字顯得太浪費(fèi),且價格也相對較高。所以不用此種作為顯示。
方案二:
采用LED數(shù)碼管動態(tài)掃描,雖然LED數(shù)碼管價格適中,但要顯示多個數(shù)字所需要的個數(shù)偏多,功耗較大,顯示出來的只是拼音,而不是漢字。所以也不用此種作為顯示。
方案三:
采用LCD液晶顯示屏,液晶顯示屏的顯示功能強(qiáng)大,可顯示大量字符,且視覺效果較好,外形美觀。LCD1602可實現(xiàn)顯示2行十六個字符。
1.3.4、 電路設(shè)計最終方案決定
綜上各方案所述,對此次作品的方案選定:采用80C51作為主控制系統(tǒng); LCD1602液晶帶漢字庫顯示屏作為顯示部分。
二、硬件設(shè)計
2.1、電路設(shè)計模塊圖如圖
AT89C51
LCD162
按鍵控制模塊
2.3、 用proteus仿真軟件仿真并抓圖。
三、軟件設(shè)計
3.1、畫出各個函數(shù)流程圖。
3.1.1、LCD1602液晶顯示控制流程圖如圖
3.1.2、調(diào)時函數(shù)控制流程如圖
實訓(xùn)心得:通過為期一周的單片機(jī)實訓(xùn),是我們對這門課有了許多新的了解,彌補(bǔ)了在課堂上學(xué)習(xí)的不足。相信這對我們以后的學(xué)習(xí)和工作都會有很大的幫助。我們一定要在最短的時間里對這些不足加以改正! 在試訓(xùn)中有苦有甜,當(dāng)我們?yōu)橐粋€很難攻破的程序找出路時,心情煩躁,感覺自己很不可理喻,當(dāng)程序一點一點編好后,自己從心底感覺到一點小小的安慰,看著自己的成果。感覺很欣慰??偠灾?單片機(jī)課程設(shè)計對于我們有很大的幫助,我們從中受益匪淺。
程序代碼。
#include
#define uchar unsigned char
#define uint unsigned int
uchar a,count,S1num,xqnum;
uchar yue,ri,shi,fen,miao;
uint nian;
sbit lcdrs=P2^5;
sbit lcdrw=P2^4;
sbit lcden=P2^3;
sbit S1=P3^0; //定義鍵--進(jìn)入設(shè)置
sbit S2=P3^1; //定義鍵--增大
sbit S3=P3^2; //定義鍵--減小
sbit S4=P3^3; //定義鍵--退出設(shè)置
uchar code table0[]="2015-01-11 SUN";
uchar code table1[]="00:00:00";
uchar code xingqi[][3]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/**************************************************
1602液晶顯示器模塊
*************************************************/
void write_com(uchar com) //液晶寫指令
{
lcdrw=0;
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar dat) //液晶寫數(shù)據(jù)
{
lcdrw=0;
lcdrs=1;
P0=dat;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/********************************************
年月日寫入1602函數(shù)
********************************************/
void write_sfm(uchar add,uchar dat) //寫時分秒函數(shù)
{
uchar shi,ge;
shi=dat/10;
ge=dat%10;
write_com(0x80+0x40+add);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_yr(uchar add,uchar dat) //寫月日函數(shù)
{
uchar shi,ge;
shi=dat/10;
ge=dat%10;
write_com(0x80+add);
write_data(0x30+shi);
write_data(0x30+ge);
}
void write_nian(uchar add,uint dat) //寫年函數(shù)
{
uint qian,bai,shi,ge;
qian=dat/1000;
bai=dat%1000/100;
shi=dat%100/10;
ge=dat%10;
write_com(0x80+add);
write_data(0x30+qian);
write_data(0x30+bai);
write_data(0x30+shi);
write_data(0x30+ge);
}
/***************************************************
1602初始化
***************************************************/
void init_lcd() //液晶初始化
{
lcden=0;
nian=2015;
yue=1;
ri=11;
shi=0; //初始shi、fen、miao
fen=0;
miao=0;
write_com(0x38); //設(shè)置16x2顯示,5x7點陣,8位數(shù)據(jù)口
write_com(0x0c); //設(shè)置開顯示,不顯示光標(biāo)
write_com(0x06); //寫一個字符后地址指針加1
write_com(0x01); //顯示清0,數(shù)據(jù)指針清0
}
void init() //初始化函數(shù)
{
init_lcd(); //液晶初始化
write_com(0x80); //設(shè)置顯示初始坐標(biāo)
for(a=0;a<14;a++) //顯示年月日初始值
{
write_data(table0[a]);
delay(5);
}
write_com(0x80+0x40); //設(shè)置顯示初始坐標(biāo)
for(a=0;a<8;a++) //顯示時分秒初始值
{
write_data(table1[a]);
delay(5);
}
write_nian(0,nian);
write_sfm(6,miao); //分別將shi、fen、miao送去液晶顯示
write_sfm(3,fen);
write_sfm(0,shi);
count=0;
xqnum=0;
S1num=0; //初始化全局變量count
TMOD=0x01; //設(shè)置定時器0工作模式1
TH0=(65535-50000)/256; //定時器裝初始值
TL0=(65535-50000)%256;
EA=1; //開總中斷
ET0=1; //開定時器0中斷
TR0=1; //啟動定時器0
}
/**************************************************
獨(dú)立鍵盤
*************************************************/
void keyscan()
{
if(S1==0)
{
delay(5); //確認(rèn)定義鍵被按下
if(S1==0)
{
S1num++; //定義鍵S1按下次數(shù)記錄
while(!S1); //釋放按鍵確認(rèn)
if(S1num==1) //S1按下一次時
{
TR0=0; //關(guān)閉定時器
write_com(0xc0+7); //光標(biāo)定位到秒位置
write_com(0x0f); //光標(biāo)閃爍
}
if(S1num==2) //S1按下兩次時
{
write_com(0xc0+4); //光標(biāo)定位到分位置
}
if(S1num==3) //S1按下三次時
{
write_com(0xc0+1); //光標(biāo)定位到時位置
}
if(S1num==4) //S1按下四次時
{
write_com(0x80+13); //光標(biāo)定位到星期位置
}
if(S1num==5) //S1按下五次時
{
write_com(0x80+9); //光標(biāo)定位到日位置
}
if(S1num==6) //S1按下六次時
{
write_com(0x80+6); //光標(biāo)定位到月位置
}
if(S1num==7) //S1按下七次時
{
write_com(0x80+3); //光標(biāo)定位到年位置
}
if(S1num==8) //S1按下八次時
{
S1num=0; //S1記錄按鍵次數(shù)清零
TR0=1; //開啟定時器
write_com(0x0c); //取消光標(biāo)閃爍
}
}
}
if(S1num!=0) //只有定義鍵按下后S2、S3、S4才有效
{
if(S2==0)
{
delay(5); //防抖
if(S2==0) //確認(rèn)按鍵被按下
{
while(!S2); //釋放按鍵確認(rèn)
if(S1num==1) //S1按下一次時
{
miao++; //調(diào)整秒加1
if(miao==60) //滿60清零
miao=0;
write_sfm(6,miao); //每調(diào)節(jié)一次送液晶顯示一次
write_com(0x80+0x40+6); //顯示位置重新回到調(diào)節(jié)處
}
if(S1num==2) //S1按下兩次時
{
fen++; //調(diào)整分加1
if(fen==60)
fen=0;
write_sfm(3,fen);
write_com(0x80+0x40+3);
}
if(S1num==3) //S1按下三次時
{
shi++; //調(diào)整時加1
if(shi==24)
shi=0;
write_com(0x80+0x40);
write_sfm(0,shi);
}
if(S1num==4) //星期加調(diào)整
{
xqnum++;
if(xqnum==7)
xqnum=0;
write_com(0x80+0x0b);
for(a=0;a<3;a++)
{
write_data(xingqi[xqnum][a]);
delay(5);
}
}
if(S1num==5) //日加調(diào)整
{
ri++;
if(yue==2)
{
if(nian%400==0)
{
if(ri==30)
{
ri=1;
}
}
if(nian%400!=0)
{
if(ri==29)
{
ri=1;
}
}
}
else if(yue<=7)
{
if(yue%2==0&yue!=2)
{
if(ri==31)
{
ri=1;
}
}
else if(yue%2!=0&yue!=2)
{
if(ri==32)
{
ri=1;
}
}
}
else if(yue>=8)
{
if(yue%2==0)
{
if(ri==32)
{
ri=1;
}
}
else if(yue%2!=0)
{
if(ri==31)
{
ri=1;
}
}
}
write_yr(8,ri);
}
if(S1num==6) //月加調(diào)整
{
yue++;
if(yue==13)
yue=1;
write_yr(5,yue);
}
if(S1num==7) //年加調(diào)整
{
nian++;
if(nian==2019)
nian=2014;
write_nian(0,nian);
}
}
}
if(S3==0)
{
delay(5);
if(S3==0) //確認(rèn)按鍵被按下
{
while(!S3);
if(S1num==1)
{
miao--; //調(diào)整秒減1
if(miao==-1) //減到00后再減重新設(shè)置為59
miao=59;
write_sfm(6,miao);
write_com(0x80+0x40+6);
}
if(S1num==2)
{
fen--; //調(diào)整分減1
if(fen==-1)
fen=59;
write_sfm(3,fen);
write_com(0x80+0x40+3);
}
if(S1num==3)
{
shi--; //調(diào)整時減1
if(shi==-1)
shi=23;
write_sfm(0,shi);
write_com(0x80+0x40);
}
if(S1num==4)
{
xqnum--; //調(diào)整星期減一
if(xqnum==-1)
xqnum=6;
write_com(0x80+0x0b);
for(a=0;a<3;a++)
{
write_data(xingqi[xqnum][a]);
delay(5);
}
}
if(S1num==5) //調(diào)整日
{
ri--;
if(yue==2)
{
if(nian%400==0)
{
if(ri==0)
{
ri=29;
}
}
if(nian%400!=0)
{
if(ri==0)
{
ri=28;
}
}
}
else if(yue<=7)
{
if(yue%2==0&yue!=2)
{
if(ri==0)
{
ri=30;
}
}
else if(yue%2!=0&yue!=2)
{
if(ri==0)
{
ri=31;
}
}
}
else if(yue>=8)
{
if(yue%2==0)
{
if(ri==0)
{
ri=31;
}
}
else if(yue%2!=0)
{
if(ri==0)
{
ri=30;
}
}
}
write_yr(8,ri);
}
if(S1num==6) //調(diào)整月
{
yue--;
if(yue==0)
yue=12;
write_yr(5,yue);
}
if(S1num==7) //調(diào)整年
{
nian--;
if(nian==2013)
nian=2018;
write_nian(0,nian);
}
}
}
if(S4==0) //退出設(shè)置、開啟中斷
{
delay(5);
if(S4==0)
{
S1num=0;
TR0=1;
write_com(0x0c);
}
}
}
}
/**************************************************
定時器0
*************************************************/
void timer0() interrupt 1 //定時器0中斷服務(wù)程序
{
TH0=(65535-50000)/256; //重裝定時器初始值
TL0=(65535-50000)%256;
count++; //中斷次數(shù)累加
if(count==20) //20次50毫秒即一秒
{
count=0;
miao++;
if(miao==60) //秒加到60時分進(jìn)位
{
miao=0;
fen++;
if(fen==60) //分加到60時時進(jìn)位
{
fen=0;
shi++;
if(shi==24) //時加到24時清0
{
shi=0;
xqnum++;
ri++;
if(yue==2) //如果是二月
{
if(nian%400==0) //閏年判斷
{
if(ri==30)
{
ri=1;
yue++;
write_yr(5,yue);
}
}
if(nian%400!=0) //平年判斷
{
if(ri==29)
{
ri=1;
yue++;
write_yr(5,yue);
}
}
}
else if(yue<=7&yue!=2) //一月到七月
{
if(yue%2==0) //偶數(shù)月(除二月)
{
if(ri==31)
{
ri=1;
yue++;
}
}
else if(yue%2!=0) //奇數(shù)月
{
if(ri==32)
{
ri=1;
yue++;
}
}
write_yr(5,yue);
}
else if(yue>=8) //八月到12月
{
if(yue%2==0) //偶數(shù)月(除二月)
{
if(ri==32)
{
ri=1;
yue++;
if(yue==13) //如果判斷月份為12月,則加一后重新定義月份為1
{
yue=1;
nian++;
write_nian(0,nian);
}
write_yr(5,yue);
}
}
else if(yue%2!=0) //奇數(shù)月
{
if(ri==31)
{
ri=1;
yue++;
write_yr(5,yue);
}
}
}
write_yr(8,ri);
if(xqnum==7) //星期寫入
xqnum=0;
write_com(0x80+0x0b);
for(a=0;a<3;a++)
{
write_data(xingqi[xqnum][a]);
delay(5);
}
}
write_sfm(0,shi); //重新寫入數(shù)據(jù)
}
write_sfm(3,fen); //重新寫入數(shù)據(jù)
}
write_sfm(6,miao); //重新寫入數(shù)據(jù)
}
}
/*************************************************
主函數(shù)
*************************************************/
void main()
{
init();
while(1)
{
keyscan(); //不停的檢測按鍵是否被按下
}
}
鏈接地址:http://kudomayuko.com/p-6544878.html