精品单片机课程设计报告电子万年历设计定Word文件下载.docx
《精品单片机课程设计报告电子万年历设计定Word文件下载.docx》由会员分享,可在线阅读,更多相关《精品单片机课程设计报告电子万年历设计定Word文件下载.docx(38页珍藏版)》请在冰豆网上搜索。
该设计可以在两个4位数码管上显示时、分、秒、年、月、日、星期等信息。
硬件组成简单,主要是单片机的数码管显示电路,晶振电路和按键电路。
可以在程序中预先设置每一分钟的某一段时间用来显示时、分、秒和星期信息,另一段时间显示年、月、日和星期信息。
可以看到时、分、秒和年、月、日交替显示。
同时利用按键可以切换时间的显示。
2.2小组工作描述:
小组经过讨论,确定好课题,阅读了相关书籍。
刘升发主要负责写汇编程序和焊接电路;
曾子亮主要负责整理设计报告。
刘妞负责硬件检测,提供帮助和建议
2.3资源安排:
本设计使用了一个12M晶振,两个33PF瓷片电容,一个10uF电容,四个10K电阻,一个2K电阻,一个1K的8脚上拉排阻,一块AT89C51单片机,2个4位的共阳数码管,4个按键和导线若干。
用AT89C51单片机定时器来产生时间,并执行动态扫描,用数码管显示时间。
用4个按键实现时间的切换显示功能。
2.4设计原理:
为了实现电子万年历的功能,首先要使时间可以变化,每过一秒单片机的时间也要加一秒,因此我们采用了定时器来产生时间。
而12M晶振下AT89C51单片机的定时器采用工作方式1定时的最大定时时间为65.535ms,为了实现时间秒加一,我们设定定时器每10ms溢出一次,计算出定时器的初值是TH0=0D8H,TL0=0F0H。
用一个变量来统计定时器的溢出次数,每当定时器溢出100次,我们就让秒加1,这样我们就可以得到准确的时间秒。
秒加到60后,让秒清零,分加1;
判断分加到60以后,分清零,时加1;
判断时加到24后,时清零,日期和星期加1;
判断日期到了31后,日期置1,月加1;
判断月加到13后,月置1,年加1;
判断年加到100时,年清零;
判断星期加到8后,星期置1。
这样时间的正确变化就实现了。
得到时间后,就要考虑怎么来显示了。
我们采用数码管的动态扫描来显示时间。
在两个4位共阳数码管上,一次只能显示时、分、秒、和星期信息。
时和分,分和秒之间用小数点来区分。
秒和星期之间用一横来区分。
同理,显示年、月、日、星期时年和月,月和日之间用小数点来区分,日和星期之间用一横来区分。
那什么时候让数码管显示时分秒星期,什么时候显示年月日星期呢?
我们可以在程序中设定。
比如我们可以设定每分钟的40~44秒的时候显示年月日,其余时间显示时分秒。
让数码管的动态扫描每次都扫描32H~39H单元里面的内容,而在40~44秒时我们往32H~39H里面送时分秒星期的值,在其余时间我们往32H~39H送年月日星期的值。
这样就实现了万年历的显示问题。
实现了时间的产生和显示问题后,还有一个按键功能的实现问题。
时间日期的显示调整设定了4个按键。
按键1用来暂停时间,这个很简单,只要关闭中断总开关,时间就不能加了,实现了暂停时间的功能。
按键2则用来选择需要显示的时间是日期(年、月、日)信息。
由于前面显示时间中就考虑到了时间的切换,我们只要让按键按下后进入往32H~39H送年月日星期的程序就可以了。
按键3实现恢复时间秒加1,只要再次打开终端就可以了。
按键4功能为单片机的自身的复位。
3硬件电路
硬件电路主要是单片机最小系统。
包括单片机、晶振电路、复位电路。
总体原理图如下:
复位电路:
当单片机系统在运行中,受到环境干扰出现程序跑飞的时候,按下复位按钮内部的程序自动从头开始执行。
复位电路由电容串联电阻构成,由"
电容电压不能突变"
的性质可以知道,当系统一上电,RST脚将会出现高电平,并且,这个高电平持续的时间由电路的RC值来决定。
当RST脚的高电平持续两个机器周期以上就将复位,所以,适当组合RC的取值就可以保证可靠的复位。
这里我们取R4=2K和C3=10uf,R5=10K.
晶振电路:
单片机最小系统起振电容C2、C3一般采用15~33pF,并且电容离晶振越近越好,晶振离单片机越近越好。
上拉电阻
P0口为开漏输出,作为输出口时需加上拉电阻,接数码管时,阻值一般为1K。
硬件仿真结果:
软件升级,按键功能增加后的仿真图如下:
4 软件流程
4.1汇编语言流程
汇编软件流程中,主函数设定了了定时器溢出时间为10ms,通过中间变量CHISHU来控制溢出达100次,也就是1秒后万年历的秒加1。
中间变量SHEZHI用来控制中断开关。
在PANDUAN2程序中来确定时分秒年月日星期有没有达到最大值,达到最大值后又从最小值重新循环。
SFM程序获得时分秒的个位十位分别送到数码管动态扫描扫描的存储单元中,同理NYR程序获得年月日的个位十位送到相应存储单元中。
通PANDUAN这个变量来控制执行SFM或执行NYR程序。
主函数随时都在检测按键按下与否。
按键按下后通过改变中间变量的值来实现按键的功能。
显示子程序中每次都扫描完32H~39存储单元的值。
显示子程序还用ZHONGJIANZHI这个变量实现了时和分,分和秒之间用小数点来区分,年和月,月和日之间用小数点来区分。
中断子程序中,可以判断溢出次数,溢出达到100次,秒就加1.具体流程图如下:
NO
4.2C程序流程
C程序中我们增加了按键功能。
万年历增加了时间的调整功能。
按键1的功能是暂停时间。
按键2确定修改时间的位数,按下5次后可以恢复时钟。
按键3可以使按键2选择好的位数时间加1。
按键子程序:
显示子程序如下:
主程序:
5完整程序清单
5.1汇编程序如下:
//本程序用于实现电子万年历的作用,通过定时器0的定时10ms
//加上软件定时循环100次达到准确的1秒钟
//初始时间为12年02月21日08时18分32秒星期二
//首先显示08.18.32-2之后显示12.02.21-2,星期一直显示
//通过判断中间变量使秒在40-45秒时显示年月日星期(12.02.21-2)
//在其余时间显示时分秒星期(08.18.32-2)
//硬件有4个按键,按键1:
暂停,按键2:
显示日期(年月日星期)
//按键3:
恢复,按键4:
单片机自带的复位按键
NIANDATA40H//年
YUEDATA41H//月
RIQIDATA42H//日
SHIDATA43H//时
FENDATA44H//分
MIAODATA45H//秒
XINGQIDATA46H//星期
XIABIAODATA47H//中间变量
TIMESDATA48H//时间次数
PANDUANBIT49H//控制年月日和时分秒的显示时间
SHEZHIBIT50H//设置时间
CHISHUDATA51H//定时器循环次数
OVERTIMEEQU100//定时器循环次数100
ZHONGJIANZHIDATA52H//中间变量
SHUCHUDATA53H//中间变量
ORG0000H
LJMPMAIN
ORG000BH
LJMPCTC2
ORG0030H
MAIN:
//主程序开始
MOVNIAN,#12//初始化:
12年
MOVYUE,#02//02月
MOVRIQI,#21//21日
MOVSHI,#08//08时
MOVFEN,#18//18分
MOVMIAO,#32//32秒
MOVXINGQI,#02//星期二
SETBPANDUAN
SETBSHEZHI
MOVSP,#5FH
MOVCHISHU,#OVERTIME//定时器初始化
MOVTH0,#0D8H//装初值
MOVTL0,#0F0H//装初值
MOVTMOD,#00000001B//设置工作方式
SETBET0//该中断等
SETBTR0
SETBEA
MOVZHONGJIANZHI,#00//初始化中间值
MOVSHUCHU,#00//初始化中间值
DIS:
MOVR5,#40
DIS1:
LCALLXIANSHI
DJNZR5,DIS1//循环40次
JBSHEZHI,TIAOZHUAN1
CLREA//中断关闭
TIAOZHUAN1:
//控制判断位
MOVA,MIAO//当秒等于45S后,显示时、分、秒、星期
CJNEA,#45,PANDUAN1
PANDUAN1:
CJNEA,#40,PANDUAN2//当秒等于40S后,显示年、月、日、星期
CLRPANDUAN
PANDUAN2:
//第一段显示代码开始
MIAO2:
MOVA,#60
SUBBA,MIAO
CJNEA,#0,SFM//秒等于60分时清零
MOVMIAO,#00H
INCFEN//分++
FEN2:
SUBBA,FEN
CJNEA,#0,SFM//分等于60分时清零
MOVFEN,#00H
INCSHI//时++
SHI2:
MOVA,#24
SUBBA,SHI
CJNEA,#0,SFM//时等于24分时清零
MOVSHI,#00H
INCXINGQI//星期++
INCRIQI//日++
XINGQI2:
//一直在最后两位显示
MOVA,#7
SUBBA,XINGQI
CJNEA,#0,SFM//星期等于7时清零
MOVXINGQI,#00H
//第二段显示代码开始
RIQI2:
MOVA,#30
SUBBA,RIQI
CJNEA,#0,NYR//天数等于30天时清零
MOVRIQI,#00H
INCYUE//月++
YUE2:
MOVA,#12
SUBBA,YUE
CJNEA,#0,NYR//月等于12月时清零
MOVYUE,#00H
INCNIAN//年++
NIAN2:
MOVA,#100
SUBBA,NIAN
CJNEA,#0,NYR//年等于100年时清零
MOVNIAN,#00H
//输入数据显示秒、分、时、星期
SFM:
JNBPANDUAN,NYR
MIAO1:
//秒钟
MOVA,MIAO
MOVB,#10
DIVAB
MOV35H,A
MOV34H,B
FEN1:
//分钟
MOVA,FEN
MOV37H,A
MOV36H,B
SHI1:
//小时
MOVA,SHI
MOV39H,A
MOV38H,B
XINGQI1:
//星期
MOV33H,#0AH
MOV32H,XINGQI
LJMPDIS
//输入数据,显示日、月、年
NYR:
JBPANDUAN,SFM
RIQI1:
MOVA,RIQI//天数
YUE1:
//月份
MOVA,YUE
NIAN1:
//年份
MOVA,NIAN
WEIMA:
DB01111111B,10111111B,11011111B,11101111B,11110111B,11111011B,11111101B,11111110B
DISPTAB:
DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H
//断码0、1、2、3、4、5、6、7、8、9、—
XIANSHI:
//显示程序开始
PUSHPSW
PUSHACC
MOVTIMES,#8//循环8次,扫描8个数码管
MOVXIABIAO,#00H
MOVR0,#32H
XUNHUAN:
MOVP0,#00H//消隐
MOVA,XIABIAO
MOVDPTR,#WEIMA
MOVCA,@A+DPTR
MOVP2,A
MOVA,@R0
MOVDPTR,#DISPTAB
MOVCA,@A+DPTR
MOVSHUCHU,A
MOVA,ZHONGJIANZHI
MOVB,#2
MOVA,B
CJNEA,#0,TIAO3//判断是否为偶数位,在第二.四位后面点亮小数点
LCALLTIAO2
TIAO3:
MOVP0,SHUCHU
INCXIABIAO
INCR0
INCZHONGJIANZHI
CJNEA,#08,TIAO1
MOVZHONGJIANZHI,#00
TIAO1:
ANJIAN:
//按键检测开始并执行相应程序
JBP1.0,ZHUXIANSHI//按键1:
暂停,关闭定时器,使秒数不加
LCALLANJIAN1
ZHUXIANSHI:
JBP1.1,ANJIAN3//按键2:
显示日期(年、月、日、星期)
LCALLANJIAN2
ANJIAN3:
JBP1.2,FUWEI//按键3:
恢复,打开定时器,使秒数加
LCALLFUWEI1
FUWEI:
DJNZTIMES,XUNHUAN
POPACC
POPPSW
RET
ANJIAN1:
//按键1子程序
CLRSHEZHI
POPACC
ANJIAN2:
//按键2子程序
RET
FUWEI1:
//按键3子程序
TIAO2:
//小数点子程序:
点亮2、4位小数点6、8位不点亮
CJNEA,#00,TIAO6
LJMPTIAO5
TIAO6:
CJNEA,#02,TIAO4
TIAO4:
ORLSHUCHU,#80H
TIAO5:
CTC2:
//定时器中断程序,每秒钟秒数加1
DJNZCHISHU,NEXT
MOVCHISHU,#OVERTIME
INCMIAO
NEXT:
CLRTF0//重装初始值
MOVTH0,#0D8H
MOVTL0,#0F0H
RETI
END
5.2C语言程序清单:
//本程序是通过定时器0产生1S准确时间的电子万年历
//通过8位数码管交替显示:
年\月\日\星期和时\分\秒\星期
//并在修改时间时,相应位数可以闪烁
//有三个按键;
按键1:
停止按键;
//按键2:
确定修改哪位数据,并在按下5次后恢复时钟
//按键3:
修改对应位的数据
#include<
reg51.h>
unsignedcharTable[11]=
{0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};
//段码
vart_init();
//函数申明
Updata_LED1();
Updata_LED2();
Delay();
Delay1();
Xiugai();
Xiugaishu();
sbitled0=P2^0;
//定义P2各口
sbitled1=P2^1;
sbitled2=P2^2;
sbitled3=P2^3;
sbitled4=P2^4;
sbitled5=P2^5;
sbitled6=P2^6;
sbitled7=P2^7;
sbitstop=P1^0;
//定义P10--P12口
sbitwei=P1^1;
sbitjia=P1^2;
unsignedintmiao=32;
//秒
unsignedintfen=18;
//分
unsignedintshi=8;
//时
unsignedintriqi=21;
//日
unsignedintyue=2;
//月
unsignedintnian=12;
//年
unsignedintxingqi=2;
//星期
bitqufen=0;
//区分显示年\月\日\星期或时\分\秒\星期
bitzhanting=0;
//保持按键1按下后允许执行的程序段
intweishu=0;
//判断此时修改哪位数据
intncounter=0;
//定时器循环次数
intcounter=0;
intZJ=3;
//定时器T1内部自加变量
bitzhongj1=0;
//判断修改时间时的闪烁位数
bitzhongj2=0;
bitzhongj3=0;
bitzhongj4=0;
bitzhongj5=0;
bitzhongj6=0;
bitzhongj7=0;
bitzhongj8=0;
main()//主程序开始
{
vart_init();
//定时器初始化
while
(1)
{
Updata_LED1();
//判断子程序
Updata_LED2();
//显示子程序
if(miao==40)//秒等于40秒时显示日期(年\月\日\星期)
{
qufen=1;
}
if(miao==45)//秒等于45秒时显示时间(时\分\秒\星期)
qufen=0;
}
if(stop==0)//判断按键1是否按下并执行后面程序
zhanting=1;
if(zhanting==1)//判断按键1按下,并调用按键子程序
{
Xiugai();
}
}
}//主程序结束
Xiugai()//按键子程序:
暂停,判断是否执行数据修改
TR0=0;
//关闭定时器T0
if(wei==0)//判断按键2是否按下并执行相应程序
weishu++;
Delay1();
if(weishu==6)//当按键2按下6次后打开中断
{//并关闭数据修改子程序,恢复时钟继续运行
TR0=1;
//打开定时器T0
zhanting=0;
weishu=0;
}
}
Xiugaishu();
}
Xiugaishu()//数据修改子程序
if(qufen==0)//判断此时显示为时\分\秒\星期
switch(weishu)
{
case
(1):
if(jia==0)//检查按键3是否按下并执行下面程序
{
shi++;
//时++
Delay1();
//消抖
};
break;
case
(2):
fen++;
//分++
case(3):