数字时钟参考资料Word文档下载推荐.docx
《数字时钟参考资料Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《数字时钟参考资料Word文档下载推荐.docx(33页珍藏版)》请在冰豆网上搜索。
4.4位选及数码管驱动电路
为了让数码管的显示更清晰,我选用74HC573锁存器来驱动数码管。
由于8位数码管的显示是经过一位一位显示的,当它的扫描频率在50Hz~100Hz之间时,我们就不会看出它的位显示,并且显示的亮度正好合适,数码管的位选我通过3-8译码器74HC138,具体连接关系如下图所示:
4.5单片机最小系统
单片机的最小系统由4部分构成,分别是:
单片机、振荡电路、复位电路、RAM和ROM。
具体组成如下所示:
单片机最小系统图
4.6电源电路
单片机正常工作是+5V电压,本次设计不做电源部分,采用USB供电,由于USB供电较为稳定,所以不需要稳压部分,直接给单片机供电,这样就减少了7805稳压模快。
具体电路如下所示:
USB供电
5、PCB板的制作
本次设计的数字钟系统中由于频率不是特别高,所以在设计PCB板时不存在考虑走线之间频率干扰问题,但由于设计规定了PCB板的大小为7*9cM,并且是单面板,所以对我们的设计带来了一定的难度,在设计中不得不通过走飞线的方式完成PCB板的制作。
5.1PCB板的制作规则
我在数字钟设计中采用Orcad软件平台,完成了PCB的制作,在PCB的设计中需注意以下的一些规则:
(1)在Orcad中制作PCB时一定要注意板层的设置,我们本次设计的是单面板,所以需将Bottom层设为走线层,TOP层设为丝印层(DOC层),别的板层全部设为不走线层。
(2)由于本次设计的单面板大小规定为7*9Cm,所以在开始制定板框大小时,在Global层画边框时,将其设置为规定的大小,然后根据一定的规则放置元件,放置元件时应让元件间的走线距离最小。
(3)放置元件时须注意一些规则,例如将单片机的晶振和电容靠近单片机放置,将电源供电的USB接口靠近板框放置等。
(4)在放置完元件之后,进行布线时需注意一些走线时的设置,最重要的是元件过孔的孔径设置,为了制作方便,本次制作设为0.6mm、0.8mm、1.2mm,当然,设置了孔径,还需注意焊盘的大小,软件默认的焊盘大小一般太小,焊接时不太方便;
其次是走线的安全间距设置,走线间距一般默认为软件的设置,即0.3mm;
下来就是走线的一些规则设置,如果是自动布线,则可设置布线时的一些规则,如果是手工布线,则可根据需要进行布线。
(5)在走线时一定要注意电源走线的设置,电源的走线一定要宽,这样承载的电流会更大,电流的大小与走线的宽度之间有一定的计算公式,可以作参考。
为了使单面板的布线方便,飞线更少,我们将地线设为敷铜种子,在敷铜时与大面积的铜相接。
5.2飞线的处理
由于制作的是单面板,难免有很多的飞线,在制作完PCB板之后,需处理飞线。
经常选取的办法是打过孔,这样在加工之后可以采用飞线将其连接。
当然,飞线的多少取决于布线的水平高低。
有时为了减少飞线而走很远的路,这样带来高频的影响,我觉得这种方法应该避免。
5.3PCB制作中的注意事项
(1)要注意焊盘的大小、过孔的大小、走线的安全间距及走线的宽带,在适当的时候应该用游标卡尺进行测量,保证元器件能够合适的插进去。
(2)对于一些自己制作的原件封装,一定要测量使之合理。
(3)电源走线一定要宽,实际上是越宽越好,但过宽会影响布线的效率。
适当的时候我们可以大概的计算一下,使之更加合理。
(4)在布线时我们一定要弄清楚板层,有时一个放错了板层的字符,会带来制作时的困难,要想合理的完成制作,必须清楚板层。
(5)首次在PCB板上放置USB接口,一定要注意正负极不能接反。
(6)如果有必要,可以在每个芯片的VCC极和GND极之间跨接一个0.01~0.1uF之间的瓷片电容。
为了使电源电压稳定,可以在电源电压与地之间接一个滤波电容,如果电源电压波动较大,则可以使用稳压芯片来稳压。
(7)在敷完铜之后,需要观察敷铜区域,避免有些接地的敷铜区域形成孤岛。
如果存在孤岛,则需要与最近敷铜区连接起来,经常采用打过孔走飞线的方式使其连接起来。
(8)在放置元件时,由于设置了安全间距,元件放置较近时会出现报错提示,但这对PCB板的制作是没影响的。
6、软件模块的设计
本次设计单片机数字钟,供可选择的语言有汇编语言和C语言两种选择,从总体角度考虑,两种语言各有其优缺点。
汇编语言在编写过程中可以较容易的计算出机器周期,这样可以计算出相应的延时与误差,并且在编译过程中精度较高,执行效率也较高,是各种语言中执行效率最高的一种。
相反,汇编语言又是一种较为低级的语言,编写起来难度较大,程序量也较大,不易编写大规模的系统。
C语言它的灵活性较强,语法功能也比较强大,对于同一个设计,与汇编语言相比,工作量较小,完全可以实现汇编无法实现的一些功能。
虽然C语言具有强大的功能,但也有不足之处,比如在循环延时时不易计算出相应的机器周期,还有,采用不同的编译器,可能以不同的方式编译出不同的机器码。
由于本次设计的单片机数字钟编程量较大,又考虑到后面的工作过程中将大量使用C语言编程,所以本次编写过程采用C语言,基于KielC3软件来完成软件模块的设计工作。
6.1数字钟总体设计框图
编程设计数字钟大家可能最常用的就是采用单片机中的定时器定时的方法,由于定时器不能一次定时1s,所以需采用定时一定的时间,循环叠加的方法,加到一秒后,将其显示的秒加一,然后判断分和时是否加一,这样就完成了数字钟的最基本制作。
我在此次设计中采用的方法完全不同于上面的常规方法,主要是受到了EDA中并行的影响,当然,单片机中是不可能实现并行的,但我们可以用串行的方式模拟并行,实现数码管的扫描及采用延时粗略计算出1s的延时,这样很多人可能认为不准确,但我们可以分好多的延时,这样在校时时不会出现改一个数字出现大的变化的情况。
程序设计框图如下:
6.2源程序
源程序见附件Ⅰ。
7、设计中的问题分析与解决
由于这是我第一次系统地进行设计,难免会遇到很多的问题。
当然,作为我们初学者来说,遇到问题越多收获也就也多,这就要看我们解决问题能力及方案了。
下面是我在这次设计中所遇到的一些问题总结。
(1)由于此次设计数字钟,主要是由软件来完成的,所以硬件中的问题相对来说较少。
当我们将PCB板设计完之后,焊接上元件之后,如果出现不正常工作的情况,我们可以确定是硬件问题。
解决方案:
①检查单片机是否正常工作,我们可以使用示波器进行观察单片机ALE(第30引脚)的输出波形,如果输出波形的频率是晶振频率的6分频,则证明单片机是正常工作的。
②如果单片机第31引脚没有输出波形,首先应检查晶振的好坏,我们可以更换晶振看其是否能正常工作。
③如果还不正常工作,说明是硬件电路的设计有问题,首先我们应该检查的是所有芯片的电源是否正常。
(2)我们采用C语言,利用单片机中的优点中断和定时器,完成数字钟其实很容易实现,但要完成精度相当高的数字钟设计,加上实现校时和闹钟功能之后,我们会遇到很多的问题。
首先是怎么避免由按键造成的延时误差,我们总结的方案有4种,分别是:
①计算出按键延时的具体时间,按键一次则给定时器加上相应的按键延时时间,这样虽然可以大大的减小按键延时带来的时间误差,但还是有一定量的机器周期的延时。
例如使用这种方法又需在定时器中添加一些判断语句,当符合条件时,将会增加一定的机器周期。
②通过采用设置优先级的方式可以清除按键防抖延时,在主程序中我们需要将定时器的中断优先级设为最高,别的中断优先级设为低,这样我们在按键中断时,如果定时器还未中断,则响应外部中断,这样对定时器的定时没有影响;
如果在响应外部中断的时候,有定时中断,则优先响应定时中断,这样又对定时器的定时没有影响;
如果在响应定时中断时,则别的中断不会影响到定时器的正常定时。
(3)在设定闹钟时间时,我们要确保定时器的正常工作,如何既要让数码管显示闹钟设置的相应时间,并且定时器的正常计数不能受到影响,我们应该如何解决这个矛盾呢?
解决方案:
为了使编程更加方便,我们专门设置了一个启动设置闹钟的开关,当开关设为高电平时,则为闹钟设置,首先数码管上全部显示零,即清零。
然后按相应的校时按钮,则数码管显示被设置的相应时间,在设置闹钟的这期间,是如何确保相应时间的准确性呢?
我是这样解决的,当启动设置闹钟开关之后,在程序中同时启动另一个定时器开始定时工作,当定到50ms时,发生中断,相应的变量加一,这样我们就可以计算出在设置闹钟时所花费的时间。
当设置闹钟开关置到相应的低电平时,说明设置闹钟结束,在这同时,我们将变量所记的数与50ms相乘,计算出与之对应的秒数,加到闹钟设置之前保存到静态变量中的数上。
这种方法有一定的缺陷,会造成一定的延时,经过软件处理,延时将在0~0.5s之间随机产生。
(4)在测量数字钟精度时,我们发现了一个问题,在数字钟正常工作时,会出现秒与秒之间不相等的情况,比如在10分钟之内我们与标准时间进行比较会发现,有时发现时间走的快,有时时间走的慢。
后面在程序中发现,原因是由于程序中的if判断语句,在判断过程中当满足条件时,会执行更多的语句,这样会有相应的机器周期的延时,所以会出现时间一会走的快一会走的慢的情况。
这种情况只有通过减少if语句,怎么减少if语句呢?
我们可以充分利用单片机的自身条件,充分利用单片机中的定时器,定时器不够用时我们可以选用89c52系列。
8、设计总结与心得
单片机数字钟可以说是一个较小的系统,开始时我们觉得通过C语言较容易实现,确实,只实现一个能够正常走时并且能够校时的数字钟是比较容易的。
但我们想错了,毕竟是第一次从总体角度来考虑地完成一个小系统,好多的实际性的问题我们没有考虑,所以造成我们最终设计的数字钟精度不高,并且存在好多问题,当然问题多了对我们来说是好事,这样我们在解决更多问题时学会更多解决问题的方法,对我们也算是长长经验吧。
最开始我们需要总体设计,这就是常常说的算法。
平时的编程实现的都是小功能,我们按照自己的想法直接写下去就可以实现,但这次不一样,我们不但要实现数字钟的正常工作,而且需要加上设置闹钟及闹钟到报警和是否已经设置了闹钟的指示灯提示,这在我们设计时会遇到好多的矛盾,当然矛盾我们可以一个个的解决,当然更重要的是在解决矛盾时我们要确保时间的准确性,这又需要我们计算机器周期和处理一些延时程序的延时,这可能是我们本次设计中最困难的问题,我们在解决这个问题中更深入的理解了单片机的内部结构,也学会了合理利用单片机中的定时器和中断处理。
除了在编写程序中遇到的问题之外,我对程序又有了更深一层的认识,就像王老师经常说的那样,人类只是现在还没有弄清楚人类的思维方式,如果有一天生物科技真正研究通了人类自己的思维方式,机器人将真的会有自己的思维方式,可能真的就会战胜人类了。
在这次设计中,让我真的明白了,只要我们想明白的事情,我们一定会用程序将其描述出来,不管它有多么的复杂。
接下来就是PCB的制作,这次可算是经历了全部过程,从画原理图到PCB的导出,最后到生产加工出成品,尤其是PCB板的加工生产过程尤为重要,从生产加工中我们可以学到很多在画PCB时的注意事项,也理解了我们在软件中的各种设置的重要性及0.2mm的差距。
看着加工机床的机械臂在那儿来回着工作,就像拉鞋垫一样,一针一线地完成了整个版图。
非常震撼的是自动化的强大。
这次数字钟的设计主要是用单片机来完成的,虽然我们也花了很多时间来完成它的总体设计,但就像老师说的那样,这只是个开始。
从这次设计中我也觉得自己还对单片机的功能了解只是个皮毛,单片机强大的功能还等着我们去开发。
在这些天大家总结报告时我发现,我们大家的意识还太低,就像写个报告,大家总在意的是看谁写了多少页了,看谁的程序多,所占用的页数多,一切似乎和页数联系上了。
我觉得我们更应该去关注一下大家所写的程序,看谁的程序在完成同样功能的同时,他采用方法新颖,程序占用的内存少,并且精度高。
看来我们大家总被一种错误的观念领导着,面对内存有限的单片机而言,编写一个数字钟,我们无论采用的哪种方法都不可能用完单片机内部的程序存储器,我觉得我们现在所做的事都是为我们后面做铺垫的,所以我们现在就应该去关心程序所占用的内存和采用的优于别人的算法。
所以我们在程序中减少冗余量,在此我举几个例子,比如在程序中比较是否闹钟时间到时,我们完全可以采用单片机没有用的标志位F0,当闹钟时间和当前时间相同时,将F0置1,然后判断F0是否为1,如果是1则响闹钟,这样我们可以减少变量的定义。
利用C语言写时,难免会定义一些静态变量,这些静态变量相当于一些寄存器,我们可以重复利用这些静态变量,这样会减少更多静态变量的定义,即可以节约内存。
最后我觉得系统的设计需要我们全面着去考虑好多的问题,这对我们的成长会有更大的帮助。
程序的实现不只是功能的实现,还要有可靠的稳定性,占用的内存也要较小。
附录Ⅰ
/***********************************************
*文件名:
计数器1.c
*描述:
本次设计一个数字钟,能够较准确的计时,
并能对时,还附有闹钟的功能
*创建人:
张满归
*时间:
20110101-20110120
***********************************************/
#include<
reg52.h>
stdio.h>
#include<
INTRINS.H>
#defineucharunsignedchar
#defineuintunsignedint
sbits0=P2^0;
sbits1=P2^1;
sbits2=P2^2;
sbitd1=P3^2;
sbitd2=P3^3;
sbitsclk=P1^0;
//设置闹钟
sbitcclk=P1^1;
//关闭闹铃
sbitbell=P1^2;
sbitlclk=P1^3;
staticintk1=0;
staticintk2=0;
//秒高位
staticintk3=0;
staticintk4=0;
//分高位
staticintk5=0;
staticintk6=0;
//时高位
//staticintF;
//k2*10+k1
staticintc2=0;
//k4*10+k3
staticintc3=0;
//k6*10+k5
staticintj1,j2,j3,j4,j5,j6;
staticintc=0;
ucharcodetable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
*名称:
voiddelay2()
*功能:
去抖动延时
*输入:
无
*输出:
voiddelay2(void)//去抖动
{
uinti,j;
for(i=0;
i<
3;
i++)
for(j=0;
j<
1800;
j++)
;
}
voiddelay1()
数码管显示动态扫面延时
voiddelay1(void)
{uintn;
for(n=50;
n>
0;
n--)
}
voiddelay()
主程序延时,方便计数精确
voiddelay(void)
{uintm;
for(m=9;
m>
m--);
voidEX0_time()
外部中断0服务程序
voidEX0_time()interrupt0
delay2();
if(d1==0)
{if(k6==0||k6==1)
{if(k5==9)
{k5=-1;
k6++;
}
elseif(k6==2)
{if(k5==3)
{k6=0;
k5=-1;
}
k5++;
voidEX1_time()
外部中断1服务程序
voidEX1_time()interrupt2
{delay2();
if(d2==0)
{if(k3==9)
{k3=-1;
if(k4==5)
k4=-1;
k4++;
}
k3++;
voidbell_call()
闹钟服务程序
/*voidbell_call(void)
{TMOD=0x10;
TH0=0xFF;
//1ms
TL0=0xFF;
TR1=1;
ET1=1;
EA=1;
}*/
voidT1_bell()
T1中断服务程序,输出方波驱动蜂鸣器
/*voidT1_bell()interrupt3
TR1=0;
bell=~bell;
}*/
voidshaomiao()
8位数码管扫面显示
voidshaomiao(void)
{
if(F0==1)
while(s0==0&
&
s1==0&
s2==0)
{
P0=table[k6];
delay1();
P0=0x00;
s0=1;
s1=0;
s2=0;
while(s0==1&
P0=table[k5];
delay1();
s0=0;
s1=1;
s1==1&
P0=0x40;
P0=table[k4];
s2=1;
s2==1)
{if(F0==1)
P0=table[k3];
s0=1;
{
P0=table[k2];
P0=table[k1];
voidset_clk()
设置闹钟时开定时
器0和类