单片机电子时钟课程设计实验报告Word下载.docx
《单片机电子时钟课程设计实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《单片机电子时钟课程设计实验报告Word下载.docx(21页珍藏版)》请在冰豆网上搜索。
每按一次键,对应的显示值便加1。
分、秒加到59后再按键即变为00;
小时加到23后再按键即变为00。
在调校时均不向上一单位进位(例如分加到59后变为00,但小时不发生改变)。
5)软件设计必须使用MCS-51片内定时器,采用定时中断结构,不得使用软件延时法,也不得使用其他时钟芯片。
6)设计八段数码管显示电路并编写驱动程序,输入并调试拆字程序和数码显示程序。
7)掌握硬件和软件联合调试的方法。
8)完成系统硬件电路的设计和制作。
9)完成系统程序的设计。
10)完成整个系统的设计、调试和制作。
11)完成课程设计报告。
基本要求
1)实现最基本要求的1~10部分。
2)键盘输入可以控制电子时钟的走时/调试。
3)设计键盘输入电路和程序并调试。
4)掌握键盘和显示配合使用的方法和技巧。
提高发挥部分
1)另设三个键,分别作小时、分、秒的减1调校。
2)在以上设计的基础上,修改程序制作一个电子秒表。
分、秒各占用2位显示,1/10秒、1/100秒各占用1位显示。
设定二个键分别作启动/停止、清零(清零应在停止后有效)。
3)在做完
(2)后,将时钟与秒表合二为一,并且在同时使用时互不影响,即可在时钟与秒表之间任意切换,而不影响走时、计秒。
整体设计框图及整机概述
整体设计框图
整机概述
1)开机为走时模式,正常显示时间。
在此模式下,时钟可调。
2)共设置7个按键,分别为模式键、功能键、加一键、减一键、复位键、秒表启动键、秒表复位键。
按动模式键,模式将在‘走时/调时/显示及秒表显示及调整’2个模式下切换。
3)在时钟模式下,功能键选择是正常走时,还是进入调试(时、分、秒)模式。
4)按动加一键可以将值(时、分、秒)加一。
5)按动减一键可以将值(时、分、秒)减一。
6)按动秒表中开始/暂停按键可以随时控制秒表的开始和停止。
7)按动秒表中清零按键时,秒表计的数就会被清除(只有在秒表停止了以后)。
8)按下复位键后,无论是任何状态都会从新开始。
9)开机时钟与闹钟都为00:
00:
00。
各硬件单元电路的设计、参数分析及原理说明
电源电路
元件有限没有制作电源电路部分。
使用9V的电池经过7805稳压后进行供电。
按键
参考书本P232的键盘接口电路原理图,P3口(除去P3.6)接的是键盘按键。
当按键按下后,P3口被拉成低电平,给单片机一个信号,使单片机产生一个中断。
单片机再指令相应的P0口,P2口产生变化。
单片机最小系统
参考实验指导书与课本及网络资料设计按键电平复位。
LED数码管
首先P0口作为段码输出。
由于P0口输出级无上拉电阻,故需添加一排阻为其上拉电阻。
其次采用共阳极数码管。
段码端为低电平时导通LED,此时数码管向89S51芯片P0口灌电流,为防止芯片烧坏,还需加1个1KΩ的限流电阻。
考虑到数码管的亮度问题,采用了PNP三极管做驱动电路。
基极接上1KΩ电阻后再与P2口相连(P2.0~P2.5)进行位选。
发射极接5V电源,集电极接数码管位选。
软件流程图和流程说明
软件流程图
1)主程序流程图
流程图说明
初始化:
包括定时器赋
初值,初始化各内存单
元。
开定时器中断,开
CPU中断。
时间显示及调整子程序与秒表显示及调整子程序流程图与调时模式子程序大同小异。
总结设计及调试体会
硬件设计部分:
首先要通过计算与参考资料等决定参数。
而后通过仿真软件等调试,确定参数无误后再开始用AD画原理图,进而生成PCB进行布板。
在焊板子的时候,也出现了问题,不小心将7805焊成了7905,结果又调试了一个时间。
软件设计部分:
设计软件首先要考虑要做的功能,确定出合理的算法。
合理的算法不仅要可以实现功能,而且在添加功能的时候要方便灵活。
有的人为了实现某种功能用了各种各样的方法来实现,结果程序结构吃死,当想要添加功能或者修改其他功能的时候,将修改程序大部分结构,也就是说要破坏程序现有的结构。
关于调试:
Keil软件调试单片机程序的时候,编译通过并不代表程序是正确的。
编译通过只能说明程序没有语法上的错误。
进行软件仿真或者下载到开发板上进行调试,经常会出现各种各样的错误。
许多超出预期效果的现象往往是一些微小错误引起的。
例如没有现场保护跟恢复现场等,所以养成良好的编程习惯也很重要。
有些想达成某些功能而添加的语句,实际上确一点效果也没有。
举个编程中的小问题:
当有按键按下时,我们都要有软件防抖。
正常的方法是调用一个延时。
在实际调试中,要跳过这个抖动,需要100MS左右。
如果使用正常的延时,会导致按键按下时CPU100MS内无法进行其他操作,也就是说。
平均1S内100MS不调用显示子程序,这样就会导致亮度降低。
这时候,考虑到显示子程序一次有十几毫秒,就特别写了一个程序来作为按键防抖的延时,实际上效果也是很不错的。
这个想法就是在修改了多次程序未达到想要的效果(有按键按下时显示亮度不降低)后最终想出来的办法。
最后在做完板,焊完电路后,在接通电源之前,要用万用表仔细检查电路是否有连接错,以免烧坏芯片和数码管。
设计课设的其他体会:
态度要积极,不要认为很简单就不紧不慢。
很多东西并不是自己设想的那么顺利,有时候一个小问题可以花上你半天甚至一天的时间。
虽然自己在程序上并没遇到太大的问题,但是因为态度不够积极,对于没画过的PCB图迟迟不去下手,在周四晚上才解决。
本以为周五一天可以做完板并完成整机调试,可是各种突发事件让自己措手不及。
发现板来不及做完后才将程序功能进行扩展。
这是我在这次实验中的一个教训,也让我明白了对于自己不能太过于自信,态度决定一切。
图一:
系统电路原理图
图二:
系统电路PCB
在protues中调试的结果
在开发板上实现的效果(见实物)
在焊的PCB板子上效果(见实物)
在protues里的仿真以及在开发板上实现和自己做实物所看到的现象是不一样的。
在protues里不用接三极管(NPN)就可以实现效果,但是在自己做板子的时候就不行了,因为51单片机的输出的电流不能驱动数码管发光,需要一个增加驱动的9014三极管。
另外,protues里的复位按键不起作用(软件里就是这样设计的)。
将在PCB上实现的程序用在开发板上又出现了问题,delay(3)这个延时子程序不合理,出现了闪烁的问题,所以将delay(3)改成了delay
(1),这样问题就解决了。
我是将三极管加在了段选上,又加了限流电流,这样做数码管也能点亮。
另一方面,一样的程序用在不同的显示上,现象也是不一样的。
所以,我需要不断地修正定时器的装值。
TH1=(65536-49997)/256;
//重装初值
TL1=(65536-49997)%256;
TH0=(65536-8000)/256;
TL0=(65536-8000)%256;
经过实际测量,这个数值是最合适的,一个小时一秒不差。
表一:
元器件清单
器件名称
数量
电池
一个
Lm7805
自锁开关
51单片机
LED
两个
极性电容
非极性电容
晶振
10K电阻
九个
1K电阻
七个
100电阻
八个
PNP三极管
4位数码管(共阴)
时钟程序源码
#include<
reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
ucharcodetable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
sbitled=P1^1;
//指示灯
sbitqiehuan_key=P3^7;
//秒表和时钟模式切换按键
sbitsp_key=P3^4;
//秒表中开始/暂停按键
sbitclf_key=P3^5;
//秒表中清零按键
sbitfunc_key=P3^1;
//时钟换位按键(时、分、秒)
sbitadd_key=P3^2;
//时钟加1按键
sbitsub_key=P3^3;
//时钟减1按键
uchark1_bit=0;
//切换按键标志位
ucharshi1,shi2,fen1,fen2,miao1,miao2,fen3,fen4,miao3,miao4,num9,num10;
uintnum1,num2,num3,num4,num5,num6,num7,num8,num11;
voiddelay(uintxms)//延时函数
{
uinti,j;
for(i=xms;
i>
0;
i--)
for(j=110;
j>
j--);
}
voidinit()//中断初始化函数
EA=1;
//开总中断
TMOD=0X11;
//定时器工作方式选择,定时器0和定时器1都选择第1种工作方式
TH0=(65536-10000)/256;
//定时器0装初值,定时10ms(用于秒表)
TL0=(65536-10000)%256;
ET0=1;
//开定时器0开关
TR0=0;
//开定时器0小开关
TH1=(65536-50000)/256;
//定时器1装初值,定时50ms(用于时钟)
TL1=(65536-50000)%256;
ET1=1;
//开定时器1开关
TR1=1;
//关定时器1小开关
voidmode_key()//模式选择键,本程序两种模式,分别是时间显示、秒表。
当K1_bit为0时显示时钟,为1时进入秒表
if(qiehuan_key==0)
{
delay(5);
if(qiehuan_key==0)
{
k1_bit++;
if(k1_bit==2)
{
k1_bit=0;
}
while(!
qiehuan_key);
}
}
voiddisplay1(ucharshi1,ucharshi2,ucharfen1,ucharfen2,ucharmiao1,ucharmiao2)//显示时钟函数
shi1=num1/10;
shi2=num1%10;
fen1=num2/10;
fen2=num2%10;
miao1=num3/10;
miao2=num3%10;
P2=0xff;
P0=table[shi1];
//第一位
P2=0xfe;
delay(3);
P0=table[shi2];
//第二位
P2=0xfd;
P0=0x40;
//第三位
P2=0xfb;
P0=table[fen1];
//第四位
P2=0xf7;
P0=table[fen2];
//第五位
P2=0xef;
//第六位
P2=0xdf;
P0=table[miao1];
//第七位
P2=0xbf;
P0=table[miao2];
//第八位
P2=0x7f;
voiddisplay0(ucharfen3,ucharfen4,ucharmiao3,ucharmiao4,ucharnum9,ucharnum10)//显示秒表函数
fen3=num8/10;
fen4=num8%10;
miao3=num7/10;
miao4=num7%10;
num9=num6;
num10=num5;
P0=table[fen3];
P0=table[fen4];
P0=table[miao3];
P0=table[miao4];
P0=table[num9];
P0=table[num10];
voidkey_miaobiao()
if(k1_bit==1)
{
if(sp_key==0)
if(sp_key==0)
{
TR0=~TR0;
while(!
sp_key)
display0(fen3,fen4,miao3,miao4,num9,num10);
if(TR0==0)
led=0;
if(clf_key==0)
delay(5);
if(clf_key==0)
led=1;
clf_key)
{
num5=num6=num7=num8=0;
}
}
}
voidkeyscan()//时钟按键扫描
if(func_key==0)
delay(5);
if(func_key==0)
num11++;
while(!
func_key);
if(num11==1)
TR1=0;
if(num11==2)
TR1=1;
if(num11==3)
if(num11==4)
num11=0;
}
if(num11!
=0)
if(add_key==0)
if(add_key==0)
add_key);
if(num11==1)
num3++;
if(num3==60)
num3=0;
if(num11==2)
num2++;
if(num2==60)
num2=0;
if(num11==3)
num1++;
if(num1==24)
num1=0;
}
if(sub_key==0)
if(sub_key==0)
sub_key);
num3--;
if(num3==-1)
num3=59;
num2--;
if(num2==-1)
num2=59;
num1--;
if(num1==-1)
num1=23;
voidmain()
init();
led=0;
while
(1)
mode_key();
switch(k1_bit)//模式选择
case0:
display1(shi1,shi2,fen1,fen2,miao1,miao2);
//显示时间
keyscan();
break;
case1:
display0(fen3,fen4,miao3,miao4,num9,num10);
//显示秒表
key_miaobiao();
//扫描秒表操作
}
voidTime1()interrupt3//定时器1函数(时钟)
TH1=(65536-49997)/256;
TL1=(65536-49997)%256;
num4++;
if(num4==20)
num4=0;
num3++;
if(num3==60)//秒针
num3=0;
num2++;
if(num2==60)//分针
num2=0;
num1++;
if(num1==24)//时针
num1=0;
voidTime0()interrupt1//定时器0函数(秒表)
TH0=(65536-8000)/256;
//重装初值
TL0=(65536-8000)%256;
num5++;
if(num5==10)
num5=0;
num6++;
if(num6==10)
num6=0;
num7++;
if(num7==60)
num7=0;
num8++;
if(num8==60)
num8=0;
}
}