51单片机课程设计闹钟程序设计.docx
《51单片机课程设计闹钟程序设计.docx》由会员分享,可在线阅读,更多相关《51单片机课程设计闹钟程序设计.docx(25页珍藏版)》请在冰豆网上搜索。
![51单片机课程设计闹钟程序设计.docx](https://file1.bdocx.com/fileroot1/2023-4/20/75673b81-b408-41b4-894e-285b92da1e3d/75673b81-b408-41b4-894e-285b92da1e3d1.gif)
51单片机课程设计闹钟程序设计
沈阳航空航天大学
课程设计报告
课程设计名称:
微机系统综合课程设计
课程设计题目:
闹钟程序设计
院(系):
计算机学院
专业:
计算机科学与技术
班级:
学号:
姓名:
指导教师:
说明:
结论(优秀、良好、中等、及格、不及格)作为相关教环节考核必要依据;格式不符合要求;数据不实,不予通过。
报告和电子数据必须作为实验现象重复的关键依据。
学术诚信声明
本人声明:
所呈交的报告(含电子版及数据文件)是我个人在导师指导下独立进行设计工作及取得的研究结果。
尽我所知,除了文中特别加以标注或致谢中所罗列的内容以外,报告中不包含其他人己经发表或撰写过的研究结果,也不包含其它教育机构使用过的材料。
与我一同工作的同学对本研究所做的任何贡献均己在报告中做了明确的说明并表示了谢意。
报告资料及实验数据若有不实之处,本人愿意接受本教学环节“不及格”和“重修或重做”的评分结论并承担相关一切后果。
本人签名:
日期:
年月日
沈阳航空航天大学
课程设计任务书
课程设计名称
微机系统综合课程设计
专业
计算机科学与技术
学生姓名
班级
学号
题目名称
闹钟程序设计
起止日期
2015
年
6
月
29
日起至
2015
年
7
月
12
日止
课设内容和要求:
一、课程设计内容
设计一个数字显示的闹钟程序,具体内容如下:
1、闹钟能设定2个任务;
2、在数码管上显示剩余时间;
3、用发光二极管显示闹钟输出。
二、课程设计要求
1、认真查阅相关资料;
2、独立设计、调试并通过指导教师现场验收;
3、撰写课程设计报告
参考资料:
[1]张毅刚.单片机原理及应用[M].哈尔滨:
哈尔滨工业大学出版社,2008
[2]戴仙金.51单片机及其C语言程序开发实例[M].北京:
清华大学出版社,2011
[3]黄惟公.单片机原理与应用技术[M].西安:
西安电子科技大学出版社,2010
教研室审核意见:
教研室主任签字:
指导教师(签名)
年
月
日
学生(签名)
年
月
日
课程设计总结:
单片机是一门应用性很强的学科,课程设计是培养我们综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对我们实际工作能力的具体训练和考察过程。
虽然在做课程设计以前已经系统的把单片机课本认真的学习了一下,但是在刚拿到设计任务书时还是有点一头雾水,不知道该从哪里下手。
不过经过两周的学习,虽然过程很艰辛,但是总算实现了定时闹钟的功能,所有的努力都很值得。
这两周的大部分时间都在研究程序怎么处理,但是在这个过程中加深了我对单片机这门学科的理解,而且也学到了更多的知识。
通过这次课程设计,使我对这门功课有了更深刻的认识和了解。
使我懂得了理论与实际相结合的重要性,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,才能提高自己的实际动手能力和独立思考的能力。
其次,软件在这次设计中也有不足之处,比如闹钟无法显示剩余时间,但又不知道从哪个地方入手解决这个问题,这要求在以后的学习中,拓宽自己的知识面,解决设计的不足之处。
总之,通过这次课程设计不仅使我巩固了本课程所学的基本知识,还使我具有了撰写科研报告的初步训练能力,我相信这些能力在我以后的工作或者是再学习中一定会起到不小的作用,一切的辛苦和艰难都是值得的。
1总体设计方案
1.1课程设计的内容和要求
本设计是定时闹钟的设计,由MCS51单片机芯片和LED数码管为核心,辅以必要的电路,构成的一个单片机电子定时闹钟。
定时闹钟设计采用单片机来完成,用数码管显示“时”,“分”,“秒”。
使用MCS51系列单片机,单片机结合七段显示器设计的简易定时闹铃时钟,可以设置现在的时间、闹钟定时的时间,可以设置两个闹钟,若时间到则用发光二极管显示。
1.2课程设计原理
MCS51系列单片机内部有两个定时器,可以实现一定时间的定时,可以设置1秒的时长作为闹钟的单位时间,以此实现时钟的走时,单片机有32条I/O口线,5个中断源、一个全双工串行口等,可以通过数码管显示当前时间以及闹钟时间。
1.3课程设计思路
本设计通过设置定时器,实现时长为1秒的定时,作为时钟的单位时间,实现时钟的走时,外部按键连接到P1口,实现对时钟及闹钟的设定。
可以显示并设置两个的闹钟时间,开关功能如下:
K1:
秒调整;
K2:
分调整;
K3:
时调整;
K4:
秒归零;
K5:
时钟归零;
K6:
设置闹钟1;
K7:
按下显示闹钟设定时间,抬起显示时钟时间;
K8:
设置闹钟2。
2详细设计方案
2.1实现方法
电子闹钟应包括秒信号发生器、时间显示电路、按键电路以及闹铃指示电路等几部分。
电子闹钟的系统框图如下所示:
2.2模块设计
2.2.1主程序流程图
2.2.2中断程序流程图
2.2.2.1基本显示模块设计
基本显示模块设计的重点是由显示代码取得相应的段码,显示段码数据的并行发送,高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟,石英表,石英钟都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调校,数字式电子钟用集成电路计时时,译码代替机械式传动,用LED显示器代替显示器代替指针显示进而显示时间,减小了计时误差,这种表具有时,分,秒显示时间的功能,还可以进行时和分的校对,片选的灵活性好。
流程图如下:
2.2.2.2时间设定模块设计
K1:
秒调整;K2:
分调整;K3:
时调整。
流程图如下:
Y
Y
2.2.2.3闹铃功能的实现
闹铃功能的实现涉及到两个方面:
闹铃时间设定和是否闹铃判别与相应处理。
闹铃时间设定模块的设计可参照时间设定模块,这里着重阐述闹铃判别与处理模块的设计问题。
闹铃判别与闹铃处理的关键在于判别何时要进行闹铃。
当时十位、时个位、分十位、分个位、秒十位、秒个位中任一位发生改变(进位)时,就必须进行闹铃判别。
译码显示电路将“时”、“分”、“秒”计数器的输出送到七段显示译码驱动器译码驱动,通过六个七段LED显示器显示出来。
闹铃电路根据计时系统的输出状态产生一脉冲信号,然后驱动发光二极管亮。
流程图如下:
Y
N
N
Y
3调试及结果分析
3.1调试步骤及方法
软件运行过程中,可以通过如下按键进行操作:
K1:
秒调整;
K2:
分调整;
K3:
时调整;
K4:
秒归零;
K5:
时钟归零;
K6:
设置闹钟1;
K7:
按下显示闹钟设定时间,抬起显示时钟时间;
K8:
设置闹钟2。
3.2实验结果
程序运行时,显示时钟初始值000000,闹钟初始值000100,运行后,时钟正常走时,此时按下K7,显示闹钟时间,按下K6,显示闹钟1时间,可以通过K1、K2、K3对闹钟1进行设置,抬起K6,按下K8,对闹钟2进行设置,然后抬起K7显示时钟时间,当闹钟1或闹钟2时间到达后,发光二极管亮。
参考文献
[1]张毅刚.单片机原理及应用[M].哈尔滨:
哈尔滨工业大学出版社,2008
[2]戴仙金.51单片机及其C语言程序开发实例[M].北京:
清华大学出版社,2011
[3]黄惟公.单片机原理与应用技术[M].西安:
西安电子科技大学出版社,2010
附录(源程序)
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
/*七段共阴管显示定义*/
ucharcode
dispcode[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0xBF,0x86,0xCB,0xCF,0xEF,0xED,0xFD,0x87,0xFF,0xDF};/*定义并初始化变量*/
ucharxdata*p=0x8004;
ucharxdata*q=0x8002;
ucharsecond=0;
ucharminite=0;
ucharhour=0;
ucharsecond1=10;
ucharminite1=0;
ucharhour1=0;
ucharsecond2=10;
ucharminite2=0;
ucharhour2=0;
ucharmstcnt=0;
uchartmp=1;
uchartmp1=1;
sbitP1_0=P1^0;//second调整定义
sbitP1_1=P1^1;//minite调整定义
sbitP1_2=P1^2;//hour调整定义
sbitP1_3=P1^3;
sbitP1_4=P1^4;
sbitP1_5=P1^5;
sbitP1_6=P1^6;
sbitP1_7=P1^7;
sbitP2_0=P2^0;
sbitP2_1=P2^1;
unsignedcharalarm_flag=0;//闹钟定时到达标志变量
/*函数声明*/
voiddelay(uchark);//延时子程序
voidtime_pro();//时间处理子程序
voiddisplay();//显示子程序
voidkeyscan();//键盘扫描子程序
voidalarm_judge(void);//闹钟定时到达判定
voidbeep1(void);//闹钟响铃程序
voidbeep2(void);//闹钟响铃程序
voidshow1(void);
voidshow2(void);//闹钟设定显示
voidbeep1(void)
{
P2_0=!
P2_0;
delay(1000);
}
voidbeep2(void)
{
P2_1=!
P2_1;
delay(1000);
}
/*****************************/
/*延时子程序*/
/****************************/
voiddelay(uchark){
ucharj;
while((k--)!
=0){
for(j=0;j<125;j++){
;
}
}
}
/**************************/
/*时间处理子程序*/
/**************************/
voidtime_pro(void){
if(tmp=1){
if(second==60)//秒钟设为60进制
{second=0;
minite++;
if(minite==60)//分钟设为60进制
{minite=0;
hour++;
if(hour==24)
//时钟设为24进制
{hour=0;}
}
}
}
}
voidtime_pro1(void){
if(tmp1==1){
if(second1==60)//秒钟设为60进制
{second1=0;
minite1++;
if(minite1==60)//分钟设为60进制
{minite1=0;
hour1++;
if(hour1==24)
//时钟设为24进制
{hour1=0;}
}
}
}
}
voidtime_pro2(void){
if(second2==60)//秒钟设为60进制
{second2=0;
minite2++;
if(minite2==60)//分钟设为60进制
{minite2=0;
hour2++;
if(hour2==24)
//时钟设为24进制
{hour2=0;}
}
}
}
/*****************************/
/*显示子程序*/
/*****************************/
voiddisplay()
{
if(tmp=1){
ucharcodesuccess[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,//共阴的数码管段选.将值送给P2口
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80,0x00};
ucharcodewema[]={0x20,0x10,0x08,0x04,0x02,0x01};//位选,0-5位数码管
//while
(1)//做一个死循环,让程序永远在while下面的大括号里面运行。
{
*q=wema[0];//位码ucharxdata*q=0x8002;
*p=success[hour/10];
delay
(1);
*q=wema[1];
*p=success[hour%10];
delay
(1);
*q=wema[2];//位码ucharxdata*q=0x8002;
*p=success[minite/10];
delay
(1);
*q=wema[3];
*p=success[minite%10];
delay
(1);
*q=wema[4];//位码ucharxdata*q=0x8002;
*p=success[second/10];
delay
(1);
*q=wema[5];
*p=success[second%10];
delay
(1);
}
}
}
voiddisplay1()
{
if(tmp1==1){
ucharcodesuccess1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,//共阴的数码管段选.将值送给P2口
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80,0x00};
ucharcodewema1[]={0x20,0x10,0x08,0x04,0x02,0x01};//位选,0-5位数码管
//while
(1)//做一个死循环,让程序永远在while下面的大括号里面运行。
{
*q=wema1[0];//位码ucharxdata*q=0x8002;
*p=success1[hour1/10];
delay
(1);
*q=wema1[1];
*p=success1[hour1%10];
delay
(1);
*q=wema1[2];//位码ucharxdata*q=0x8002;
*p=success1[minite1/10];
delay
(1);
*q=wema1[3];
*p=success1[minite1%10];
delay
(1);
*q=wema1[4];//位码ucharxdata*q=0x8002;
*p=success1[second1/10];
delay
(1);
*q=wema1[5];
*p=success1[second1%10];
delay
(1);
}
}
}
voiddisplay2()
{
ucharcodesuccess2[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,//共阴的数码管段选.将值送给P2口
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80,0x00};
ucharcodewema2[]={0x20,0x10,0x08,0x04,0x02,0x01};//位选,0-5位数码管
//while
(1)//做一个死循环,让程序永远在while下面的大括号里面运行。
{
*q=wema2[0];//位码ucharxdata*q=0x8002;
*p=success2[hour2/10];
delay
(1);
*q=wema2[1];
*p=success2[hour2%10];
delay
(1);
*q=wema2[2];//位码ucharxdata*q=0x8002;
*p=success2[minite2/10];
delay
(1);
*q=wema2[3];
*p=success2[minite2%10];
delay
(1);
*q=wema2[4];//位码ucharxdata*q=0x8002;
*p=success2[second2/10];
delay
(1);
*q=wema2[5];
*p=success2[second2%10];
delay
(1);
}
}
//******************闹钟判断函数******************************
voidalarm_judge(void)
{
if(hour==hour1&&minite==minite1&&second==second1)//定时到达设定标志1
{
beep1();
}
elseif(hour==hour2&&minite==minite2&&second==second2)
{
beep2();
}
}
voidkeyscan1(void){
if(tmp1==1){
if(P1_0==0)//按键1秒的调整
{
delay(100);
if(P1_0==0){
second1++;
if(second1==60){
second1=0;
}
}
}
if(P1_1==0)//按键2分的调整
{
delay(100);
if(P1_1==0)
{
minite1++;
if(minite1==60)
{minite1=0;}}}
if(P1_2==0)//按键3小时的调整
{
delay(100);
if(P1_2==0)
{
hour1++;
if(hour1==24)
{hour1=0;}
}
}
}
}
voidkeyscan2(void){
if(P1_0==0)//按键1秒的调整
{
delay(100);
if(P1_0==0){
second2++;
if(second2==60){
second2=0;
}
}
}
if(P1_1==0)//按键2分的调整
{
delay(100);
if(P1_1==0)
{
minite2++;
if(minite2==60)
{minite2=0;}}}
if(P1_2==0)//按键3小时的调整
{
delay(100);
if(P1_2==0)
{
hour2++;
if(hour2==24)
{hour2=0;}
}
}
}
/*******************************/
/*键盘扫描子程序*/
/*******************************/
voidkeyscan(void){
if(tmp=1){
if(P1_3==0){
second=0;
minite=0;
hour=0;
}
if(P1_4==0){
second=0;
}
if(P1_0==0)//按键1秒的调整
{
delay(100);
if(P1_0==0){
second++;
if(second==60){
second=0;
}
}
}
if(P1_1==0)//按键2分的调整
{
delay(100);
if(P1_1==0)
{
minite++;
if(minite==60)
{minite=0;}}}
if(P1_2==0)//按键3小时的调整
{
delay(100);
if(P1_2==0)
{
hour++;
if(hour==24)
{hour=0;}
}
}
}
}
voidtimer0(void)interrupt1using0//定时器0方式1,50ms中断一次
{
TH0=0x3c;
TL0=0xb0;
TMOD=0x11;
mstcnt++;
if(mstcnt==20)
{
second++;
mstcnt=0;//注意点。
对计数单元的清零十分的重要,本次调试中就是
}
}
/*闹钟设定*/
voidshow1(void)
{
if(P1_5==0){
tmp=0;
keyscan1();//按键扫描
time_pro1();//时间处理
display1();//显示时间
tmp=1;
}
}
voidshow2(void)
{
if(P1_7==0){
tmp1=0;
keyscan2();//按键扫描
time_pro2();//时间处理
display2();//显示时间
tmp1=1;
}
}
/**************************/
/*主函数*/
/**************************/
voidmain(void){
P1=0xff;//初始化p1口,全设为1
P2=0x00;//初始化p2口,全设为0
TMOD=0x11;//time0为定时器,方式1
TH0=0x3c;//预置计数初值
TL0=0xb0;
EA=1;
ET0=1;
TR0=1;
while
(1){
alarm_judge();
if(P1_6==1){
keyscan();//按键扫描
time_pro();//时间处理