资源描述
电子工艺实训2
《数字电子钟的制作》
设计报告
学院:计算机与电子信息学院
队长:1307300413 李子康
小组成员:1307200108高维春
1226211614黄凯操
指导老师: 聂雄
日期:2015.6.30
19
目录
一、任务与要求 2
二、设计思路 2
(1)时钟计数的设计 2
(2)按键控制时间的设定和调整 2
(3)定时器/计数器0实现1s计数 3
三、数字钟的组成部分 3
(1)硬件模块 3
(2)软件模块 3
四、数字钟程序设计流程图 4
五、数字钟程序设计 5
(1)数码管显示 5
(2)时钟初始化 5
(3)中断设计 5
(4)按键程序 7
六、遇到的问题 9
(1)定时时间的控制 9
(2)数码管的显示 9
七、仿真效果图 10
八、实物图 11
九、心得与体会 11
十、附录:程序代码 11
一、任务与要求
设计并制作一个数字电子钟,实现如下功能:
(a)采用数码管或LCD屏幕显示时、分和秒时间
(b)通过按键可以调整和设定当前时间
(c)要求计时准确(10分钟内计时误差<1s)
(d)设计原理图、PCB图,制作和调试电路(如果有现成的单片机板子,也可以直接使用)
(f)编写电子钟控制软件
(g)编写实训设计报告
二、设计思路
(1)时钟计数的设计
用AT89C51单片机的定时器/计数器T0产生1s的定时时间,作为秒计数时间,当一秒产生时,秒计数加1开始计时。显示00-00-00的时间,开始计时;
(2)按键控制时间的设定和调整
P1.0口控制“秒”的调整,每按一次按键加1s;
P1.1口控制“分”的调整,每按一次按键加1min;
P1.2口控制“时”的调整,每按一次按键加1h;
计时满23-59=59时,返回00-00-00重新计时。
P1.3口用做复位键,在计时过程中,如果按下它,则返回00-00-00重新开始计时。
(3)定时器/计数器0实现1s计数
单片机选择16位定时工作方式。对T0来说,系统时钟为12MHZ,最大定时也只有65535us,无法达到所需要的1s的定时,因此必须通过软件来处理这个问题,取T0的最大定时为50ms,要定时1s需要经过20次的50ms的定时。这20次计数,采用软件的方法来实现。
设TMOD=01H,设置定时器\计时器0工作在方式1 ,则 TH0=(65535-50000)/256
TL0=(65536-50000)%256
这样,当计数器/定时器0计满50ms时,产生一个中断,在中断服务程序中对中断次数加以统计,就能实现数字钟的逻辑功能了。
三、数字钟的组成部分
(1)硬件模块
单片机芯片,八位共阴数码管,驱动数码管译码的芯片74HC573(仿真时为74LS245),按键,外加电阻,导线若干;
(2)软件模块
数码管显示程序设计,定时器初始化,定时器中断编程,时钟的时、分、秒控制 ,按键程序设计,时间的调整与设定。
开始
开始
四、数字钟程序设计流程图
显示设计,设置定时器,定时50ms
开始
是
根据计数值显示时间
开始
秒键被按下?
否
否
秒计数加1
开始
分键被按下?
是
否
时键被按下?
到60s?
否 是
否
分计数加1
开始
是 否
复位键被按下?
到60min?
否 是
小时加1
开始
是
到24h?
?
否
开始
开始
是
五、数字钟程序设计
(1)数码管显示
定义数码管的位选和段选数组
uchar code wei[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar code duan[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F};
通过程序控制来选择数码管的位码和断码
(2)时钟初始化
HOUR=0;//时为0
MINITE=0;//分为零
SECOND=0;//秒为零
TMOD=0x01;//选择计数方式
TH0=(65536-50000)/256;//赋初值
TL0=(65536-50000)%256;
(3)中断设计
void Timer0(void)interrupt 1 using 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TCNT++;//控制中断次数
if(TCNT==20)
{
SECOND++;
TCNT=0;
if(SECOND==60)
{
MINITE++;
SECOND=0;
if(MINITE==60)
{
HOUR++;
MINITE=0;
if(HOUR==24)
{
HOUR=0;
MINITE=0;
SECOND=0;
TCNT=0;
}
}
}
}
}
(4)按键程序
sbit S_SET=P1^0;//定义按键控制端口
sbit M_SET=P1^1;
sbit H_SET=P1^2;
sbit RESET=P1^3;
void KEY_TEST()
{
DISPLAY();
P1=0xff;
restar=0;
if(S_SET==0);//按下控制“秒”的按键
{
delay(100);
if(S_SET==0)
{
SECOND++;
if(SECOND==60)
{
SECOND=0;
}
while(S_SET==0) DISPLAY();
}
}
if(M_SET==0);//按下控制“分”的按键
{
delay(100);
if(M_SET==0)
{
MINITE++;
if(MINITE==60)
{
MINITE=0;
}
while(M_SET==0) DISPLAY();
}
}
if(H_SET==0);//按下控制“时”的
{
delay(100);
if(H_SET==0)
{
HOUR++;
if(HOUR==24)
{
HOUR=0;
}
while(H_SET==0) DISPLAY();
}
}
if(RESET==0)//按下“复位”的按键
{
delay(100);
if(RESET==0)
{
restar=1;
}
}
}
六、遇到的问题
(1)定时时间的控制
刚开始不熟单片机的定时,在设计时间时常常达不到所要求的秒的误差,通过查阅资料,明白了定时时赋初值的计算方法,经过矫正,实验计数基本符合了实验要求的误差。
(2)数码管的显示
设置了数码管的段选和位选数组之后,怎么使它显示出想要的效果是一个很棘手的问题。解决这个问题时,我们遇到很大的困难,尤其是编好烧录后老是错乱显示。后面我们想到一种比较好的方法,就是通过时,分,秒,上的数值个位,十位来选择数码管上的数组对应的数,以达到通过数码管来显示时钟上的数值。
七、仿真效果图
八、实物图
九、心得与体会
通过本次实验设计,我对单片机的学习有了进一步地提升,特别是对中断的控制以及中断服务程序的编写,数码管的显示。同时本次试验大大地提高了我们的团队意识。
十、附录:程序代码
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit S_SET=P1^0;
sbit M_SET=P1^1;
sbit H_SET=P1^2;
sbit RESET=P1^3;
unsigned char SECOND,MINITE,HOUR,TCNT,restar=0;
uchar code wei[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar code duan[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F};
uchar dispbuf[8];
void delay(unsigned int us)
{
while(us--);
}
void SCANDISP()
{
unsigned char i,value;
for(i=0;i<8;i++)
{
P3=0xff;
value=duan[dispbuf[i]];
P0=value;
P3=wei[i];
delay(50);
}
}
void Timer0(void)interrupt 1 using 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TCNT++;
if(TCNT==20)
{
SECOND++;
TCNT=0;
if(SECOND==60)
{
MINITE++;
SECOND=0;
if(MINITE==60)
{
HOUR++;
MINITE=0;
if(HOUR==24)
{
HOUR=0;
MINITE=0;
SECOND=0;
TCNT=0;
}
}
}
}
}
void DISPLAY()
{
SCANDISP();
dispbuf[6]=SECOND/10;
dispbuf[7]=SECOND%10;
dispbuf[5]=10;
dispbuf[3]=MINITE/10;
dispbuf[4]=MINITE%10;
dispbuf[2]=10;
dispbuf[0]=HOUR/10;
dispbuf[1]=HOUR%10;
}
void KEY_TEST()
{
DISPLAY();
P1=0xff;
restar=0;
if(S_SET==0);
{
delay(100);
if(S_SET==0)
{
SECOND++;
if(SECOND==60)
{
SECOND=0;
}
while(S_SET==0) DISPLAY();
}
}
if(M_SET==0);
{
delay(100);
if(M_SET==0)
{
MINITE++;
if(MINITE==60)
{
MINITE=0;
}
while(M_SET==0) DISPLAY();
}
}
if(H_SET==0);
{
delay(100);
if(H_SET==0)
{
HOUR++;
if(HOUR==24)
{
HOUR=0;
}
while(H_SET==0) DISPLAY();
}
}
if(RESET==0)
{
delay(100);
if(RESET==0)
{
restar=1;
}
}
}
void main()
{
while(1)
{
HOUR=0;
MINITE=0;
SECOND=0;
TCNT=0;
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
IE=0x82;
TR0=1;
while(1)
{
KEY_TEST();
if(restar==1)
break;
}
}
}
展开阅读全文