实用制作:基于单片机的数显可调定时器
扫描二维码
随时随地手机看文章
随着电子技术的不断发展,人们生活水平的不断提高,充电型电子设备的种类和数量也跟着迅猛发展,尤其是电动车和手机。这些电子设备在给我们生活和工作带来便捷的同时,充电的问题也使得人们不厌其烦,电动车大约需要充电8小时左右,手机大约需要充电3小时左右,然而当充电结束后,人们经常忘记拔掉电源,更有甚者给电池充电达数天,这对电池的功能和使用寿命无疑是一种破坏。介于此,笔者萌生了自己动手设计制作一个数显可调定时器的想法,来解决一些生活中的问题。
数显可调定时器数显可调定时器原理介绍
通过小时和分钟的“加”“、减”按键对需要的定时时间进行预设,确定无误后,按下启动按键,定时开始,这时,数码管便会从预设时间开始倒计时,同时充电发光二极管每秒闪烁一次,当计时到零后,充电发光二极管由闪烁状态变成常亮,继电器动作,切断充电电源。
假如电路在运行时出现故障或者运行错误,需要按单片机的复位键,然后对定时时间重新调整后,按启动按键,重新开始定时。
电路框图如图1所示。电路原理图如图2所示。
图1 电路方框图
图2 电路原理图
1. 输入部分
输入部分有五个按键组成,分别是分钟+10、分钟-10、小时+1、小时-1和设置完成按键。定时器的初始值是8小时。
使用前,先通过这五个按键进行定时时间的设置,分钟设置键的分辨率之所以10分钟为一个步进阶梯完全是考虑的实际的需要,因为无论是电动车还是手机,都没有必要以一分钟为单位,当然,使用者可以根据自己的需要动手修改程序,已达到自己的要求。
本制作所使用的按键均为四脚封装常开型按键,使用前需通过万用表对引脚进行测量来确定那组引脚作为开关使用,当然也可以直接使用对角线引脚作为开关按键,另外两个引脚悬空,便不会出现问题。同时需要提醒的是,电路板上另外一个按键是单片机的复位按键,电路正常工作时不要去触摸。
输入部分的电路工作原理就是单片机对按键的识别,如图3所示,单片机的P1口通过上拉电阻接高电平,当没有按键按下时,P1.0~P1.4的管脚电压为高电平,如果某一个按键按下,相应的单片机并口就会被拉低为低电平。编程时,只要扫描P1.0~P1.4的状态,便能完成对按键的识别。
图3 输入部分
2. 控制部分
控制部分采用AT89S51单片机作为控制器,它把按键的信息采集过来后,经过单片机内部的定时计数器T0运算,完成相应的定时,同时单片机的并口也会将信息输出给显示部分和输出部分。
控制部分的主要工作原理就是利用了单片机内部的定时/ 计数器T 0 , 由于它的最大定时时间只有6 5 m s左右,所以,本制作利用T0的方式一,每次定时50ms,循环1200次,来实现精确的一分钟定时。误差在微秒级。
图4 单片机最小系统
3. 显示部分
显示部分由两个发光二极管和一个三位一体的数码管组成。
红色发光二极管为电源指示灯,当电源通电其发光,断电其熄灭。黄色发光二极管为充电指示灯,充电开始后,它每秒亮灭一次,充电完成后,其亮灭闪烁变为常亮。在设计阶段,笔者还建议在输出继电器加第三个发光二极管,作为继电器吸合或断开的指示灯,切忌一开始就加接强电,危险极大。
数码管是三位一体共阳极封装,高位数码管显示小时,其它两个数码管显示分钟。
数码管电路的主要工作原理就是电路驱动和动态扫描。
如图5所示,数码管的段驱动采用自带BCD译码的4线7段译码驱动器74LS247。位驱动则采用八同相三态缓冲器/线驱动器的74HC244,由于它集成了八个同相驱动器,所以可以驱动八个数码管。
图5 显示部分
数码管动态扫描就是利用人眼的视觉暂留现象,某一时刻只有一位数码管显示,其它熄灭,通过位选切换,快速的在三个数码管上依次显示所需信息,由于速度很快,加上数码管的余辉现象和人眼的视觉暂留现象,使得人们能够看到完整流畅的三个数字。
4.输出部分
输出部分主要是一个能控制220V市电通断的继电器。继电器的驱动部分则采用达林顿晶体管阵列ULN2003A(见图6)。
图6 输出部分
它其实就是集成了七个继电器驱动的集成电路,所以本制作可以扩展输出七个继电器,能满足七个用电器的七种不同定时,当然,要实现此功能还需要修改程序。读者也可以用分立元件来替代ULN2003A。
实物图及PCB版图如图7~图9所示。
图7
图8
图9
程序清单:
#include <AT89X51.H>
#defi ne uchar unsigned char
#defi ne uint unsigned int
uchar bbit[]={0x04,0x02,0x01};
uchar buffer[]={0,0,0};
uchar hour=8,minute;//小时初始值为8,分钟为00
uint count;
void delay(uchar ms)//毫秒级延时子程序
{
uchar j;
for(;ms>0;ms--)
for(j=0;j<120;j++);
}
void tt0() interrupt 1 using 1//定时器T0中断子程序
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
if(count==1200) //50ms*1200=60s(秒)
{
count=0;
if(hour==0&&minute==0)
{
P3_0=1; //继电器动作
while(1){P1_7=0;}//充电完成 灯由闪烁变常亮
}
if(minute==0)
{
minute=60; hour--;
if(hour>=9)hour=9;
}
minute--;
if(minute>=59)minute=59;
}
buffer[0]=minute%10;//秒的低位放入显示缓冲区
buffer[1]=minute/10;//秒的高位放入显示缓冲区
buffer[2]=hour; //小时放入显示缓冲区
count++;
if(count%10==0)
P1_7=!P1_7; //正在充电 充电指示灯每秒闪烁一次
}
void display()//数码管显示子程序
{uchar i;
for(i=2;i!=0xff;i--)
{
P0=buffer[i];
P2=bbit[i];
delay(10);
P0=0XFF;
}
}
void main()//主函数
{
P1=0xff; //初始化
P3=0;
TMOD=0x01;
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
EA=1;
ET0=1;
while(1)
{
buffer[0]=minute%10;
buffer[1]=minute/10;
buffer[2]=hour;
display();
if(P1_0==0)//分钟“加十”
{
delay(5);
if(P1_0==0)
{minute+=10;if(minute>=59)minute=0;} while(P1_0==0);
}
if(P1_1==0)//分钟“减十”
{
delay(5);
if(P1_1==0)
{minute-=10;if(minute>=59)minute=0;}while(P1_1==0);
}
if(P1_3==0)//小时“加一”
//P1_3和P1_2互换位置,完全是因为PCB布局的需要
{
delay(5);
if(P1_3==0)
{hour++;if(hour>=9)hour=9;} while(P1_3==0);
}
if(P1_2==0)//小时“减一”
{
delay(5);
if(P1_2==0)
{hour--;if(hour>=9)hour=9;}while(P1_2==0);
}
if(P1_4==0)break;
//如果按下设置键,跳出本循环,定时开始
}
TR0=1;
while(1)
{
display();
}
}