当前位置:文档之家› 单片机万年历实训报告

单片机万年历实训报告

单片机万年历实训报告系部:电气自动化系班级:13电信2班******指导老师:黄丽英、侯聪玲实训时间:2015年1月19日~23日用AT89C51与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与AT89C51 设计可调式电子日历时钟。

1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。

控制程序的编写等。

1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。

方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。

内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。

但造价较高。

1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。

所以不用此种作为显示。

方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。

所以也不用此种作为显示。

方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。

LCD1602可实现显示2行十六个字符。

1.3.4、电路设计最终方案决定综上各方案所述,对此次作品的方案选定:采用80C51作为主控制系统;LCD1602液晶带汉字库显示屏作为显示部分。

二、硬件设计2.1、电路设计模块图如图2.3、用proteus仿真软件仿真并抓图。

三、软件设计3.1、画出各个函数流程图。

3.1.1、LCD1602液晶显示控制流程图如图是3.1.2、调时函数控制流程如图实训心得:通过为期一周的单片机实训,是我们对这门课有了许多新的了解,弥补了在课堂上学习的不足。

相信这对我们以后的学习和工作都会有很大的帮助。

我们一定要在最短的时间里对这些不足加以改正! 在试训中有苦有甜,当我们为一个很难攻破的程序找出路时,心情烦躁,感觉自己很不可理喻,当程序一点一点编好后,自己从心底感觉到一点小小的安慰,看着自己的成果。

感觉很欣慰。

总而言之,单片机课程设计对于我们有很大的帮助,我们从中受益匪浅。

程序代码。

#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar 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; //定义键--进入设置sbit S2=P3^1; //定义键--增大sbit S3=P3^2; //定义键--减小sbit S4=P3^3; //定义键--退出设置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) //液晶写数据{lcdrw=0;lcdrs=1;P0=dat;delay(5);lcden=1;delay(5);lcden=0;}/********************************************年月日写入1602函数********************************************/void write_sfm(uchar add,uchar dat) //写时分秒函数{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) //写月日函数{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) //写年函数{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、miaofen=0;miao=0;write_com(0x38); //设置16x2显示,5x7点阵,8位数据口write_com(0x0c); //设置开显示,不显示光标write_com(0x06); //写一个字符后地址指针加1write_com(0x01); //显示清0,数据指针清0}void init() //初始化函数{init_lcd(); //液晶初始化write_com(0x80); //设置显示初始坐标for(a=0;a<14;a++) //显示年月日初始值{write_data(table0[a]);delay(5);}write_com(0x80+0x40); //设置显示初始坐标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; //初始化全局变量countTMOD=0x01; //设置定时器0工作模式1TH0=(65535-50000)/256; //定时器装初始值TL0=(65535-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/**************************************************独立键盘*************************************************/void keyscan(){if(S1==0){delay(5); //确认定义键被按下if(S1==0){S1num++; //定义键S1按下次数记录while(!S1); //释放按键确认if(S1num==1) //S1按下一次时{TR0=0; //关闭定时器write_com(0xc0+7); //光标定位到秒位置write_com(0x0f); //光标闪烁}if(S1num==2) //S1按下两次时{write_com(0xc0+4); //光标定位到分位置}if(S1num==3) //S1按下三次时{write_com(0xc0+1); //光标定位到时位置}if(S1num==4) //S1按下四次时{write_com(0x80+13); //光标定位到星期位置}if(S1num==5) //S1按下五次时{write_com(0x80+9); //光标定位到日位置}if(S1num==6) //S1按下六次时{write_com(0x80+6); //光标定位到月位置}if(S1num==7) //S1按下七次时{write_com(0x80+3); //光标定位到年位置}if(S1num==8) //S1按下八次时{S1num=0; //S1记录按键次数清零TR0=1; //开启定时器write_com(0x0c); //取消光标闪烁}}}if(S1num!=0) //只有定义键按下后S2、S3、S4才有效{if(S2==0){delay(5); //防抖if(S2==0) //确认按键被按下{while(!S2); //释放按键确认if(S1num==1) //S1按下一次时{miao++; //调整秒加1if(miao==60) //满60清零miao=0;write_sfm(6,miao); //每调节一次送液晶显示一次write_com(0x80+0x40+6); //显示位置重新回到调节处}if(S1num==2) //S1按下两次时{fen++; //调整分加1if(fen==60)fen=0;write_sfm(3,fen);write_com(0x80+0x40+3);}if(S1num==3) //S1按下三次时{shi++; //调整时加1if(shi==24)shi=0;write_com(0x80+0x40);write_sfm(0,shi);}if(S1num==4) //星期加调整{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) //日加调整{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) //月加调整{yue++;if(yue==13)yue=1;write_yr(5,yue);}if(S1num==7) //年加调整{nian++;if(nian==2019)nian=2014;write_nian(0,nian);}}}if(S3==0){delay(5);if(S3==0) //确认按键被按下{while(!S3);if(S1num==1){miao--; //调整秒减1if(miao==-1) //减到00后再减重新设置为59miao=59;write_sfm(6,miao);write_com(0x80+0x40+6);}if(S1num==2){fen--; //调整分减1if(fen==-1)fen=59;write_sfm(3,fen);write_com(0x80+0x40+3);}if(S1num==3){shi--; //调整时减1if(shi==-1)shi=23;write_sfm(0,shi);write_com(0x80+0x40);}if(S1num==4){xqnum--; //调整星期减一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) //调整日{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) //调整月{yue--;if(yue==0)yue=12;write_yr(5,yue);}if(S1num==7) //调整年{nian--;if(nian==2013)nian=2018;write_nian(0,nian);}}}if(S4==0) //退出设置、开启中断{delay(5);if(S4==0){S1num=0;TR0=1;write_com(0x0c);}}}}/**************************************************定时器0*************************************************/void timer0() interrupt 1 //定时器0中断服务程序{TH0=(65535-50000)/256; //重装定时器初始值TL0=(65535-50000)%256;count++; //中断次数累加if(count==20) //20次50毫秒即一秒{count=0;miao++;if(miao==60) //秒加到60时分进位{miao=0;fen++;if(fen==60) //分加到60时时进位{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) //偶数月(除二月){if(ri==31){ri=1;yue++;}}else if(yue%2!=0) //奇数月{if(ri==32){ri=1;yue++;}}write_yr(5,yue);}else if(yue>=8) //八月到12月{if(yue%2==0) //偶数月(除二月){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) //奇数月{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); //重新写入数据}write_sfm(3,fen); //重新写入数据}write_sfm(6,miao); //重新写入数据}}/*************************************************主函数*************************************************/void main(){init();while(1){keyscan(); //不停的检测按键是否被按下}}。

相关主题