电子万年历课程设计报告.docx
- 文档编号:26744285
- 上传时间:2023-06-22
- 格式:DOCX
- 页数:23
- 大小:193.18KB
电子万年历课程设计报告.docx
《电子万年历课程设计报告.docx》由会员分享,可在线阅读,更多相关《电子万年历课程设计报告.docx(23页珍藏版)》请在冰豆网上搜索。
电子万年历课程设计报告
课程:
创新与综合课程设计
电子与电气工程系
实践教学环节说明书
题目名称电子万年历
院(系)电子与电气工程学院
专业电子信息工程
班级119411
学号1109635010
学生姓名11
指导教师q1
起止日期13周周一~14周周五
电子万年历
1.设计目的
设计一个具有报时功能、停电正常运行(来电无需校时)、带有年月日、时分秒及星期显示的电子日历。
2.方案设计
硬件控制电路主要用了AT89S52芯片处理器、LCD1602显示器等。
根据各自芯片的功能互相连接成电子万年历的控制电路。
软件控制程序主要有主控程序、电子万年历的时间控制程序、时间显示及星期显示程序等组成。
主控程序中对整个程序进行控制,进行了初始化程序及计数器、还有键盘功能程序、以及显示程序等工作,时间控制程序是电子万年历中比较重要的部分。
时间控制程序体现了年、月、日、时、分、秒及星期的计算方法。
时间控制程序主要是定时器0计时中断程序每隔10ms中断一次当作一个计数,每中断一次则计数加1,当计数100次时,则表示1秒到了,秒变量加1,同理再判断是否1分钟到了,再判断是否1小时到了,再判断是否1天到了,再判断是否1月到了,再判断是否1年到了,若计数到了则相关变量清除0。
先给出一般年份的每月天数。
如果是闰年,第二个月天数不为28天,而是29天。
再用公式s=v-1+〔(y-1/4〕-〔(y-1/100〕+〔(y-1/400〕+d计算当前显示日期是星期几,当调节日期时,星期自动的调整过来。
闰年的判断规则为,如果该年份是4或100的整数倍或者是400的整数倍,则为闰年;否则为非闰年。
在我们的这个设计中由于只涉及100年范围内,所以判断是否闰年就只需要用该年份除4来判断就行了。
3.系统的设计框图
本系统以AT89S52单片机为核心,结合时钟芯片DS1302,LCD1602,键盘等外围器件,实现电子万年历的一系列功能,并通过液晶屏和按键控制完成人机交互的功能。
系统总体设计框图如图
(1)所示
4.系统硬件设计
1.单片机主控制模块
AT89S52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3,MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。
如图
(2)所示。
(1)内部结构
按功能分为8部分:
CUP,程序存储器,数据存储器,时钟电路,串行口,并行I/O口,中断系统,定时/计数器。
(2)引脚定义及功能
1).电源及时钟引脚
Vcc:
接+5V电源
Vss:
接地
XTAL1和XTAL2:
时钟引脚,外接晶体引线端。
当使用芯片内部时钟时,此两引脚端用于外接石英晶体和微调电容;当使用外部时钟时,用于接外部时钟脉冲信号。
2).控制引脚
RST/Vpq:
RST是复位信号输入端,Vpd是备用电源输入端。
当RST输入端保持2个机器周期以上高电平时,单片机完成复位初始化操作。
当主电源Vcc发生故障而突然下降到一定低电压或断电时,第2功能Vpd将为片内RAM提供电源以保护片内RAM中的信息不丢失。
ALE/PROG:
地址锁存允许信号输入端。
在存取外存储器时,用于锁存低8位地址信号。
当单片机正常工作后,ALE端就周期性地以时钟振荡频率的1/6固定频率向外输出正脉冲信号。
此引脚的第2功能PROG是对片内带有4K字节EPROM的8751固外程序时,作为编程脉冲输入端。
PSEN:
程序存储器允许输出端。
当片外程序存储器的读选通信号,低电平有效。
CPU从外部程序存储器取指令时,PSEN信号会自动产生负脉冲,作为外部程序存储器的选通信号。
EA/Vpp:
程序存储器地址允许输入端。
当EA为高电平时,CPU执行片内程序存储器指令,但当PC中的值超过0FFFH时,将自动转向执行片外程序存储器指令;当EA为低电平时,CPU只执行片外程序存储器指令。
3).I/O口引脚
P0.0~P0.7:
P0口8位双向I/O口;
P1.0~P1.7:
P1口8位准双向I/O口;
P2.0~P2.7:
P2口8位准双向I/O口;
P3.0~P3.7:
P3口8位准双向I/O口。
(3)片外总线结构
分为三部分:
数据总线DataBus(DB),地址总线AddressBus(AB),控制总线ControlBus(CB).
2.时钟电路模块
(1)DS1302的结构及工作原理
DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
(2)引脚功能及结构
图3所示出DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768kHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK始终是输入端。
图3ds1302
(3)数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
3.显示部分
1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。
显示电路采用LCD1602液晶显示,如图4所示,图中只画出了其相应的接口,3脚用于调节LCD1602的背光,4、5、6为LCD1602的控制口,用于控制其写入或是读出指令,7至14脚为LCD1602的数据口,将数传送到LCD1602中。
图4LCD1602显示电路
4.复位电路设计
复位电路由电阻和极性电容组成,如图5所示,通过高电平使单片机复位,在时钟电路开始工作后,当高电平的时间超过大约2us时,即可实现复位。
此复位电路为上电复位,较为简单。
若改进可以添加手动复位的功能,上电复位发生在开机加电时,由系统自动完成,手动复位通过一个按键来实现,在程序运行时,若遇到死机,死循环或程序“跑飞”等情况,通过手动复位就可以实现重新启动的操作。
手动按钮复位需要人为在复位输入端RST上加入高电平。
一般采用的办法是在RST端和正电源Vcc之间接一个按钮和一个电阻。
图5 复位电路 图6时钟振荡电路图
5.时钟振荡电路
时钟振荡电路图6所示,时钟振荡电路用于产生单片机正常工作时所需要的时钟信号,电路由两个30pF的瓷片电容和一个12MHz的晶振组成,并接入到单片机的XTAL1和XTAL2引脚处,使单片机工作于内部振荡模式。
此电路在加电后延迟大约10ms振荡器起振,在XTAL2引脚产生幅度为3V左右的正弦波时钟信号,其振荡频率主要由石英晶振的频率决定。
电路中两个电容C1、C2的作用使电路快速起振,提高电路的运行速度。
6.按键调整系统电路设计
按键电路由四个轻触开关组成,如图7所示。
按键用来调整时间,其一端直接接到单片机的端口,另一端接地,当按下按键时,相应的端口变为低电平,通过一个与门只要这四个按键有一个按下就会在P3.2检测到一低电平就触发外部中断0进入按键调节程序中,通过与个各键相连的端口P3.4_P3.7可以判断是哪个键按下,从而作相应的操作。
图7按键电路与单片机的链接
五.系统软件总体设计
本系统选用适时性强与透明度高的C语言作为编程语言,系统软件的开发全部采用KeiluVision4进行。
软件控制程序主要有主控程序、电子万年历的时间控制程序组成。
主控程序中对整个程序进行控制,进行了初始化程序及计数器、还有键盘功能程序、以及显示程序和时间控制程序是电子万年历中比较重要的部分。
时间控制程序体现了年、月、日、时、分、秒及星期的计算方法。
时间控制程序主要是定时器0计时中断程序每隔10ms中断一次当作一个计数,每中断一次则计数加1,当计数100次时,则表示1秒到了,秒变量加1,同理再判断是否1分钟到了,再判断是否1小时到了,再判断是否1天到了,再判断是否1月到了,再判断是否1年到了,若计数到了则相关变量清除0。
先给出一般年份的每月天数。
如果是闰年,第二个月天数不为28天,而是29天。
闰年的判断规则为,如果该年份是4或100的整数倍或者是400的整数倍,则为闰年;否则为非闰年。
公历与星期的换算方法
在现行公历中,历年的长度365天(平年)或者366天(闰年)都不是七的整数倍,所以日期与星期之间没有明显的对应关系。
一般情况下,不看日历牌就无法知道某月某日是星期几。
不过,它们之间还是有一定规律可循的,只要经过简单计算,或者查找表格,就可以知道与任何日期相对应的星期数。
主程序首先初始化定时器、LCD1602及DS1302,然后就开始查询按键,有键按下则开始调整时间和日期,若没有按下,则执行下面的时间、日期的显示,最后依次循环这些相同的操作,相应流程图如图8所示:
图8主程序流程图
6.系统测试与分析
按键的检测是通过中断的办法来实现,利用按键进行间调整。
K1按下则开始设置时间及日期,同时在第一行最右端显示被选择的对象,第一次按下K1时,设置年份,若按下K3,则是减1操作,按下K2是加1操作,设置好年后,第二次按下K1时,则是设置月份,按K3减,按K2则加1,依次循环下去,则可以将时间和日期设置完毕,K4是确定键,设置好按下即可保存。
通过此电子万年历设计,本系统能完成以下功能:
(1)显示公历日期功能(年、月、日、时、分、秒以及星期),
(2)可通过按键切换年、月、日及时、分、秒的显示状态,(3)可随时调校年、月、日或时、分、秒,星期,(4)可每次增减一进行时间调节,(5)停电可以正常运行。
七.结语
本系统利用AT89S52单片机进行可编程控制,结合键盘、液晶屏等,通过DS1302的使用,可以降低编写程序的复杂程度。
KeiluVision4编译软件实现单片机控制液晶显示模块的电子万年历设计,可以达到比较好的设计效果。
系统硬件电路采用成熟的电路设计,元件选用成本较低的器件,电路稳定,抗干扰力强,性价比较高。
软件开发用C语言,采用模块式结构,系统功能易于扩展。
参考资料:
[1]余锡存,曹国华.单片机原理及接口技术[M].西安电子科技大学出版社2004.
[2]张志良,主编:
单片机原理及控制技术(第2版)[M].北京:
机械工业出版社,2005.
[3]余永权,MCS-51系列单片机实用接口技术[M].北京:
北京航空航天大学出版,1993.
[4]余西存,曹国华.单片机原理及接口技术[M].西安:
西安电子科技大学出版,2000.
[5]周国运,鲁庆宾.单片机原理及应用(C语言版)[M].中国水利水电出版社,2009.
[6]周颖,俞吉.基于AT89S52单片机的电子万年历系统设计[J].现代电子技术,2012.35(13):
178-182.
附录1
电子万年历原理图
附录2
元件清单:
LCD1602显示屏
At89s52单片机
RTC
Con8
74ls164
Ds1302
电阻
电容
发光二极管
三极管若干
杜邦线若干
附录3
实验源程序:
#include
#defineuintunsignedint#defineucharunsignedchar
sbitIO=P1^0;//DS1302数据线sbitSCLK=P1^1;//DS130时钟线
sbitRST=P1^2//DS1302复位线
sbitRS=P2^0;//LCD数据/命令选择端sbitRW=P2^1;//LCD读/写控制
sbitEN=P2^2;//LCD使能端sbitK1=P3^4;//选择sbitK2=P3^5;//加
sbitK3=P3^6;//减sbitK4=P3^7;//确定uchartCount=0;
ucharMonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
uchar*WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};
ucharLCD_DSY_BUFFER1[]={"DATE00-00-00"};//显示格式
ucharLCD_DSY_BUFFER2[]={"TIME00:
00:
00"};
ucharDateTime[7];//所读取的日期时间
charAdjust_Index=-1;//当前调节的时间对象:
,,分,是,日,月,年(1,2,3,4,6)
ucharChange_Flag[]="-MHDM-Y";//(分,时,日,月,年)(不调节秒与周)
/*---------延时程序------------------*/
voidDelayMS(uintms)
{
uchari;
while(ms--){for(i=0;i<120;i++);}
}
//-----------向DS1302写入一字节------------------//
voidWrite_A_Byte_TO_DS1302(ucharx)
{uchari;
for(i=0;i<8;i++){
IO=x&0x01;//每一位与1与存入IO中
SCLK=1;SCLK=0;//一个高脉冲将数据送入液晶控制器
x>>=1;//右移
}
}
//-----------从DS1302读取一字节------------------//
ucharGet_A_Byte_FROM_DS1302()
{uchari,b=0x00;
for(i=0;i<8;i++){
b|=_crol_((uchar)IO,i);
SCLK=1;SCLK=0;//每一个高脉冲读取一位数据
}
returnb/16*10+b%16;//返回BCD码
}
//-----------从DS1302指定位置读数据------------------//
ucharRead_Data(ucharaddr)
{
uchardat;
RST=0;SCLK=0;RST=1;//RST高电平时读/写
Write_A_Byte_TO_DS1302(addr);//先写入地址
dat=Get_A_Byte_FROM_DS1302();
SCLK=1;RST=0;
returndat;
}
//---------向DS1302某地址写入数据--------------------//
voidWrite_DS1302(ucharaddr,uchardat)
{SCLK=0;RST=1;
Write_A_Byte_TO_DS1302(addr);
Write_A_Byte_TO_DS1302(dat);
SCLK=0;RST=0;//高脉冲写入数据
}
//--------------设置时间----------------//
voidSET_DS1302()
{uchari;
//写控制字,取消写保护
Write_DS1302(0x8E,0x00);
//分时日月年依次写入
for(i=1;i<7;i++)
{//分的起始地址10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递增2
Write_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));
}
Write_DS1302(0x8E,0x80);//加保护
}
//----------读取当前日期时间------------//
voidGetTime()
{uchari;
for(i=0;i<7;i++){DateTime[i]=Read_Data(0X81+2*i);}
}
//-----------读LCD状态------------------//
ucharRead_LCD_State()
{ucharstate;
RS=0;RW=1;EN=1;//输出:
D0~D7=状态字
DelayMS
(1);
state=P0;//从P0口读LCD状态
EN=0;DelayMS
(1);
returnstate;
}
//-----------忙等待------------------//
voidLCD_Busy_Wait()
{
while((Read_LCD_State()&0x80)==0x80);
DelayMS(5);
}
//-----------向LCD写数据------------------//
voidWrite_LCD_Data(uchardat)
{
LCD_Busy_Wait();
RS=1;EN=0;RW=0;//写数据,EN为高脉冲,
P0=dat;EN=1;DelayMS
(1);EN=0;
}
//-------------写LCD指令-------------------//
voidWrite_LCD_Command(ucharcmd)
{
LCD_Busy_Wait();
RS=0;EN=0;RW=0;//写指令,EN高脉冲,输出:
D0~D7=数据
P0=cmd;EN=1;DelayMS
(1);EN=0;
}
//-------------LCD初始化-------------------//
voidInit_LCD()
{
Write_LCD_Command(0x38);//设置16*2显示,5*7点阵,8位数据接口
DelayMS
(1);
Write_LCD_Command(0x01);//显示清零,数据指针清零
DelayMS
(1);
Write_LCD_Command(0x06);//写一个字符后地址指针自动加1
DelayMS
(1);
Write_LCD_Command(0x0c);//设置开显示,不显示光标
DelayMS
(1);
}
//------------------------------------------
//设置液晶显示位置
//------------------------------------------
voidSet_LCD_POS(ucharp){
Write_LCD_Command(p|0x80);//相当于在0x80基础上加入位置量
}
//----在LCD上显示字符串---------//
voidDisplay_LCD_String(ucharp,uchar*s)
{uchari;
Set_LCD_POS(p);
for(i=0;i<16;i++)
{
Write_LCD_Data(s[i]);//在固定位置显示时间日期
DelayMS
(1);
}
}
//---------日期与时间值转换为数字字符----------------//
voidFormat_DateTime(uchard,uchar*a)
{
a[0]=d/10+'0';
a[1]=d%10+'0';
}
//判断是否为闰年
ucharisLeapYear(uinty)
{return(y%4==0&&y%100!
=0)||(y%400==0);}
//求自2000.1.1开始的任何一天是星期几
//函数没有通过,求出总天数后再求星期几
//因为求总天数可能会超出uint的范围
voidRefreshWeekDay()
{uinti,d,w=5;//已知1999.12.31是周五
for(i=2000;i<2000+DateTime[6];i++)
{
d=isLeapYear(i)?
366:
365;
w=(w+d)%7;
}
d=0;
for(i=1;i {d+=MonthsDays[i];} d+=DateTime[3]; //保存星期,0~6表示星期日,星期一,二,...,六,为了与DS1302的星期格式匹配,返回值需要加1 DateTime[5]=(w+d)%7+1; } //*****年月日时分++/--********// voidDateTime_Adjust(charx) {switch(Adjust_Index) { case6: //年00-99 if(x==1&&DateTime[6]<99)DateTime[6]++; if(x==-1&&DateTime[6]>0)DateTime[6]--; //获取2月天数 MonthsDays[2]=isLeapYear(2000+DateTime[6])? 29: 28; //如果年份变化后当前月份的天数大于上限则设为上限 if(DateTime[3]>MonthsDays[DateTime[4]]) {DateTime[3]=MonthsDays[DateTime[4]];} RefreshWeekDay();//刷新星期 break; case4: //月01-12 if(x==1&&DateTime[4]<12)DateTime[4]++; if(x==-1&&DateTime[4]>1)DateTime[4]--; MonthsDays[2]=isLeapYear(2000+DateTime[
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 电子 万年历 课程设计 报告