1、 单片机万年历实训汇报 系 部:电气自动化系 班 级:13电信2班 姓 名:周祝福 指导老师:黄丽英、侯聪玲 实训时间:1月19日23日用AT89C51和LCD1602设计可调式电子日历时钟一、总体设计1.1、设计目标 为巩固所学单片机知识,把所学理论利用到实践中,用LCD1602和AT89C51 设计可调式电子日历时钟。 1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期初始状态;(3)能够用4个按键调整日历时钟年、月、日、时、分、秒和星期 ; 完成可调式电子日历时钟硬件和软件设计,包含单片机相关内容;日历时钟模块设计,液晶显示模块设计,按键模块
2、设计。控制程序编写等。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 、显示模块选择方案和论证:
3、方案一: 采取点阵式数码管显示,点阵式数码管是由八行八列发光二极管组成,对于显示文字比较适合,如采取显示数字显得太浪费,且价格也相对较高。所以不用此种作为显示。方案二: 采取LED数码管动态扫描,即使LED数码管价格适中,但要显示多个数字所需要个数偏多,功耗较大,显示出来只是拼音,而不是汉字。所以也不用此种作为显示。方案三: 采取LCD液晶显示器,液晶显示器显示功效强大,可显示大量字符,且视觉效果很好,外形美观。LCD1602可实现显示2行十六个字符。1.3.4、 电路设计最终方案决定 综上各方案所述,对此次作品方案选定:采取80C51作为主控制系统; LCD1602液晶带汉字库显示器作为显示
4、部分。二、硬件设计2.1、电路设计模块图图AT89C51LCD162按键控制模块2.3、 用proteus仿真软件仿真并抓图。三、软件设计3.1、画出各个函数步骤图。3.1.1、LCD1602液晶显示控制步骤图图3.1.2、调时函数控制步骤图实训心得:经过为期一周单片机实训,是我们对这门课有了很多新了解,填补了在课堂上学习不足。相信这对我们以后学习和工作全部会有很大帮助。我们一定要在最短时间里对这些不足加以更正! 在试训中有苦有甜,当我们为一个极难攻破程序找出路时,心情烦躁,感觉自己很不可理喻,当程序一点一点编好后,自己从心底感觉到一点小小抚慰,看着自己结果。感觉很欣慰。总而言之,单片机课程设
5、计对于我们有很大帮助,我们从中受益匪浅。程序代码。#include#define uchar unsigned char#define uint unsigned intuchar a,count,S1num,xqnum;uchar yue,ri,shi,fen,miao;uint nian;sbit lcdrs=P25;sbit lcdrw=P24;sbit lcden=P23;sbit S1=P30;/定义键-进入设置sbit S2=P31;/定义键-增大sbit S3=P32;/定义键-减小sbit S4=P33;/定义键-退出设置uchar code table0=-01-11 SUN
6、;uchar code table1=00:00:00;uchar code xingqi3=MON,TUE,WED,THU,FRI,SAT,SUN;void delay(uint z)uint x,y;for(x=z;x0;x-)for(y=110;y0;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);
7、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);
8、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=;yue=1;ri=11
9、;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;a14;a+) /显示年月日初始值write_data(table0a);delay(5);write_com(0x80+0x40);
10、/设置显示初始坐标for(a=0;a8;a+)/显示时分秒初始值write_data(table1a);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;/
11、开启定时器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
12、_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);/防抖i
13、f(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_co
14、m(0x80+0x40);write_sfm(0,shi);if(S1num=4) /星期加调整xqnum+;if(xqnum=7)xqnum=0;write_com(0x80+0x0b);for(a=0;a3;a+)write_data(xingqixqnuma);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=8)if(yue%2=0)if(ri=32)ri=1;else if(yue%2!=0)if(ri=31)ri=1;w
15、rite_yr(8,ri);if(S1num=6)/月加调整yue+;if(yue=13)yue=1;write_yr(5,yue); if(S1num=7) /年加调整nian+;if(nian=)nian=;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
16、=-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;a3;a+)write_data(xingqixqnuma);delay(5);if(S1num=5) /调整日ri-;if(yue=2)if(nian%400=0)if(ri=0)ri=29;i
17、f(nian%400!=0)if(ri=0)ri=28;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=)nian=;write_nian(0,nian);if(S4=0) /退出设置、开启中止delay(5);if(S4=0)S1num=0;TR0=1;write_com(0x0c);/*定时器0*/voi
18、d 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时清0shi=0;xqnum+;ri+;if(yue=2)/假如是二月if(nian%400=0) /闰年判定if(ri=30)ri=1;yue+;wri
19、te_yr(5,yue);if(nian%400!=0) /平年判定if(ri=29)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月,则加一后重新定义月份为1yue=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;a3;a+)write_data(xingqixqnuma);delay(5);write_sfm(0,shi);/重新写入数据write_sfm(3,fen);/重新写入数据write_sfm(6,miao);/重新写入数据/*主函数*/void main()init();while(1)keyscan();/不停检测按键是否被按下