SEG1SEG7-311SEG2SEG7-311S2S1S0NC742110127421101235398653ABCDEFGH3333ABCDEFGH986S2S1S0NCABCDEFGDPABCDEFGDPQ1CCQ2CQ3CQ4CQ51E3Q61ECBE1EB1EB1R142EBseg2BB1seg5R112S85502S85502S8550S85502S85502S85501Kseg4R121Kseg3R131K1Kseg1R151Kseg0VCCR161KVCC
图5 数码管电路原理图
图5为数码管显示电路和对应的驱动电路。本设计采用的是0.56英寸的三位共阳型
七段数码管,结构如图6所示。
共阳型数码管的结构如上图6所示,从上图可以看出,每一个LED的正极接在一起形
成
图6 0.56英寸4位共阳数码管结构图
公共端,如果要点亮每一段LED,对应的负极要给低电平,便可使LED导通发光。由于驱动一个数码管需要电流较大,如果直接接入单片机,则会因为供电不足而导致亮度很暗,甚至无法正常显示。因此有必要增加一个驱动电路,以提供更大的电流。
驱动电路有几种方案可选,比如用集成的驱动芯片,如74LS573锁存芯片,74LS245驱动芯片等。本设计采用的方法是较为简单的三极管驱动。
图5原理图已经给出了具体的驱动电路方案。每一个数码管的公共端接入一个S8550三极管,控制对应S8550三极管的导通,即可让数码管获得VCC,从而被点亮。因为S8550是PNP型三极管,所以要使其导通,则其基极应该获得低电平,也就是单片机要输出“0”给基极,方可使数码管获得VCC。同理,如果不想让数码管被点亮,则基极应该得到“1”,S8550截止,数码管无VCC。
第4页
以上可见,通过控制三极管的导通和截止,实现了一个重要的功能:选择对应数码管工作。本设计正是基于数码管的动态扫描原理,来实现8个两位数码管的正确显示。
所谓动态扫描,就是在一个时刻里,只让一个数码管工作,其余数码管不工作。紧接着下一个时刻,让另一个数码管工作,上一个数码管和其它数码管停止工作。按照这样的原理,轮流让所有的数码管一个接一个工作,并且对应工作的数码管送出对应的数据值。从宏观来看,即可看到所有数码管是同时工作一样。
这里的宏观,指的是人的眼睛。人眼有一个视觉暂留功能,即看到一个影像后不会马上消失,而是会暂留在眼里一段时间,这个时间一般是在30~40ms左右。也就是说,如果我们在这个暂留时间内不断地更新影像,则人眼看到的将是连续的画面,而不会有停顿感。如果超过这个时间,人眼就能看出来画面不连续,有闪烁感(是切换画面时间过长造成的)。 综上,本设计中有1个4位数码管,则一共有4个数码管。要在40ms时间内对所有数码管进行扫描(送数据),则每个数码管扫描时间不能超过10ms。本设计中每个数码管扫描时间设计为1ms,符合要求。 2.3.4 按键模块
本设计中,采用1个按键完成计时的开始和暂停切换功能。按键模块如图7所示:
按键模块KEYR110KS1SW-PB图7 按键模块
VCC按键设计成低电平有效,也就是说当有按键按下后,对应的IO口状态是低电平的,
单片机只要检测对应IO口的电平状态即可知道是否有按键按下。
另外,为了提高系统的抗干扰性,每个独立按键均接了一个上拉电阻。这样设计的好处是,当没有按键按下时,由于上拉电阻作用,对应IO口被上拉到VCC),也就是说按键的空闲状态是高电平。只有按键按下后,IO才被按键拉到地(低电平),从而提高了按键的抗干扰性能,减小外界的干扰。 3 系统的程序设计
系统硬件设计好以后,接紧接着需要进行软件设计。电子秒表的软件设计主要有三个方面:一是利用定时器来完成秒表的定时周期;二是利用定时中断来实现键盘的扫描,确定单片机的工作状态;三是利用单片机控制LED的输出显示。 3.1 主程序
主程序如图8所示:
第5页
初始按键检是 启/停 TR0取返回 图8 主程序图
系统主函数流程如图8所示,主要完成对按键的检测,然后对定时计数器工作状态进行关闭或者开启,从而启动或者暂停计时。 3.2 按键模块程序流程图
按键模块的流程如下图9所示:
开始 按键检否 检测到低电是 20ms去否 仍为低电是 置标志
图9 按键模块流程图
按键模块软件设计中,主要是注意按键的去抖处理。由于通常的机械按键在按下的过程中会存在一个抖动的过程,一般为5ms~10ms。在抖动过程中,会出来高低电平的变化。所以需要对抖动进行一定的处理,以避免系统误操作。通常方法有两种,第一是硬件消抖。
第6页
硬件消抖主要是运用数字电路的稳态来完成此功能。本设计利用的是软件消抖,当检测到有按键按下时,不会马上采取动作,而是需要延时一段时间,以跳过按键的抖动期,过了这段时间再去检测按键,如果仍然是按下状态,则说明是真正有按键按下,而非抖动或者外界的干扰。软件消抖在一定程度上减少了硬件成本。 if(key==0) // 起停按键按下时 {
delay(20); // 延时20ms,跳过抖动时间,再判断 if(key==0) // 确实有按键按下
TR0=~TR0; // 将TR0取反,实现每按一次,就开始计数或者暂停计数 while(!key); // 等待按键弹起 }
以上为按键检测及软件去抖代码。 3.3 数码管扫描流程图
数码管动态扫描采用T1定时器中断,流程图如下图10所示:
T1中断 送对应的段送对应的位sel自加1 是 sel为6? 否 退出中图10 扫描模块流程图
sel清0
以下为具体代码:
uchar segdata[6]={0x00,0x00,0x00,0x00,0x00,0x00};// 6个数码管的数据
uchar code select[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};// 6个数码管的位选信号 uchar code table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0-9
/*************定时器1中断****************/
void timer1_int() interrupt 3 // 扫描数码管 {
TH1=(65536-1000)/256; TL1=(65536-1000)%6;
第7页
// 注意,仿真时,由于没有用三极管驱动,位扫描要取反
//SCAN=~0xff; // 仿真时,要用这句代替下面这句 SCAN=0xff; // 需要关了所有的数码管,避免数码管有重影 if(sel==2)
PDATA=table[segdata[sel]]-0x80;// 当显示到第二个数码管时,显示计时的小数点 else if(sel==4)
PDATA=table[segdata[sel]]-0x80; // 当显示到第二个数码管时,显示计时的小 // 数点 else
PDATA=table[segdata[sel]]; // 否则是其它的数码管,则不显示小数点 //SCAN=~select[sel]; // 仿真时用这句位扫描,替代下一句 SCAN=select[sel]; // 送出数据后,再打开对应的数码管 sel++;
if(sel==6) // 扫描完4个数码管后,又开始重新扫描(从右到左扫描) sel=0;
segdata[0]=s1; // 将计时的值放到对应的显示位置 segdata[1]=s1/10; segdata[2]=s2;
segdata[3]=s2/10; segdata[4]=s3; segdata[5]=s3/10; }
本设计有6个数码管,因此sel取值为0、1、2、3、4、5,用来对应6个数码管。如上面的代码,sel=0对应的是分钟的十位,以此类推。每中断一次,送一个数码管对应的段码,同时位选也是选中该位数码管。具体选中哪个数码管,由sel来决定(sel的不同值对应不同的数码管)。当数据输出后,sel自加1,以便指向下一个数码管。等待下一个中断(间隔1ms)来临,又按上面的过程完成下一个数码管的扫描。
程序中要注意先关闭显示,然后送出段码,最后打开显示。这样做的目的是为了避免数码管出现重影现象,可以使显示更清晰。 3.4 T0计时流程图
T0定时器中断,流程图如下图11所示:
第8页