分段编码筛纸
AT89C51单片机,30秒倒计时器,发光二极管
有很多方法可以设计和制作30秒倒计时器。本文介绍的30秒倒计时定时器以AT89C51为控制单元,用两个数码管显示时间,用三个按钮分别控制定时器的计时开始、复位和暂停。倒计时器的初始状态显示“30”。当裁判按下计时器键,30秒后开始倒计时。当计时时间减少到0时,计时器会发出声光警报,提醒裁判计时时间到了。
第一,电路设计
30秒倒计时器的电路主要由电源电路、单片机最小系统、按键输入、显示驱动电路和报警电路组成。30秒倒计时定时器的控制电路如图1所示。
图1 30秒倒计时定时器电路原理图
1,按键输入
“30秒倒计时器”使用三个按钮完成开始计数、复位、暂停/继续计数等功能。
(1)K1键:开始按钮(P3.2)。
按下K1键,计数器开始倒计时,数码管显示的数字从30开始每秒倒计时。当达到零时,报警电路会发出声光报警信号。当计数器处于暂停状态时,按下K1键将返回计时状态。
(2)K2键:复位按钮(P3.3)。
按K2键,无论计数器工作在什么状态,计数器都会立即复位到预设值“30”,在报警状态下按K2键取消报警。
(3)K3键:暂停/定时开关按钮(P3.4)。
当计数器处于计时状态时,按此键暂停计时器,数码管显示的数字不变;当计数器处于暂停状态时,按下该键,计数器将回到计时状态;密钥在初始状态下无效。
2.显示驱动电路
“30秒倒计时器”采用两个* * *数码管显示时间,数码管的显示方式为动态显示。在显示驱动电路中,数码管的段管脚通过一个470欧姆的电阻连接到单片机的P1端口,两个片选管脚通过一个9012连接到正5V电源,由P3.0和P3.1控制。
4.告警电路
当计时时间减少到0时,当显示数码管显示“00”时,LED D1由P3.5控制发出光报警,蜂鸣器由P3.7控制发出声报警。
二、软件编程思路
1,全局变量
“30秒倒计时器”的动作流程主要由三个全局变量控制。一是位变量“act”,当“act”为“1”时,倒计时开始,为“0”时停止,“act”的初始值为“0”,可以设置为“1”,也可以通过按钮操作清零。第二个全局变量是char变量“time ”,它存储倒计时时间。当倒计时时间为0时,将发出声光报警。变量“时间”的初始值是30。当“act”为1时,定时器中断服务程序会每隔1减去1,减为0时保持为0。按下“重置键”将“时间”重置为30。第三个全局变量是int变量“t”,它记录响应计时被0中断的次数。根据初始化定义,定时器0工作在1模式,每1 ms发出一个中断请求..控制程序只打开定时器0中断,所以不会有比定时器0中断更高级的中断,所以每一个请求都会被立即应答。响应后,在中断服务程序中的全局变量“T”上加1,记录响应中断次数。1000次的每一次响应都是1秒。变量“t”的初始值为0,中断服务程序加上1。当“t”为2000时,它被中断服务程序清除。在键驱动器中,当按下开始键、复位键和暂停/开始键时,“t”被清除为0,以便从0 ms开始计数
2.控制流
主程序主要用于检测全局变量“时间”,当“时间”为0时发出“声光报警”。按键驱动、显示驱动和“时间”操作都在定时器0中断服务程序中进行。控制流程如图2所示。
图2控制流程图
三、软件程序设计
1,数码管驱动器
计时器的两个数码管动态显示计时时间“time”(全局变量),LED1显示十位“time”,LED2显示一位“time”。
(1)定义段代码数据端口和芯片选择信号。
根据实际电路,C51中定义的段码的数据端口为P1,两个片选信号分别为P3.0和P3.1。定义如下:
#定义段P1
sbit wei1=p3^0;
sbit wei2=p3^1;
(2)定义字体代码
LED显示数字0~9和被完全破坏的字体码表放在数组zixing[]中。字体代码是一个固定的表,在定义的时候加上关键字“code”意味着这个表存储在程序内存中。
无符号字符代码zixing[]=
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff
};
(3)定义LED1和LED2的显示变量。
为了增加驱动程序的可移植性,作者为LED1和LED2定义了显示变量。显示变量是这个驱动器的外部接口,外部程序可以通过改变显示变量的值来改变数码管显示的值。定义如下:
无符号字符led_str[2]={10,10 };
Led_str[0]直接对应LED 1,LED _ STR [1]直接对应LED2。在这个项目中,全局变量time的计算被一个特殊的子程序分为led_str[0]和led_str[1]两部分。
void js()
{
led _ str[1]= time/10% 10;
led _ str[0]= time % 10;
}
(4)数码管驱动器
数码管驱动程序“void处士(char i)”在定时中断服务程序中被调用和执行。根据初始化程序的定义,定时中断服务程序每1 ms执行一次,在定时中断服务程序中,用全局变量“t”记录进入服务程序的次数,当达到2000次时“t”被定时中断服务程序清零。
数码管驱动器的参数“char i”用于确定LED1或LED2当前是否点亮。当参数为“0”时,LED1亮,当参数为“1”时,LED2亮。如果我们想偶数次进入定时中断服务程序时点亮LED1,奇数次进入定时中断服务程序时点亮LED2,可以使用程序调用语句“处士(t % 2);”容易实现。
进入数码管驱动后,先调用子函数js()计算当前led_str[0]和led_str[1]。接下来把两个数码管都灭了,防止余辉。最后点亮需要点亮的数码管,发出字体代码。驱动程序代码如下:
无效处士(char i)
{
js();//计算显示变量
段= 0xff//去余晖
Wei 1 = I;wei2=!我;//确认电影选择
段= Zixing[led _ str[I]];//发送字体代码
}
2、关键驱动因素
按键驱动分为两部分:按键识别和按键功能执行。按键功能可以在按键时执行,也可以在按键抬起后执行,按键功能设计为在按键抬起后执行。
(1)定义关键I/O地址。
根据实际电路,三个按键(开始键、复位键、暂停/开始键)分别连接到P3端口的P3、P3.3和P3.4引脚。为了方便的获取键值,P3端口也被定义为“iokey”,可以在程序中定义如下:
#定义约基·P3
sbit key1=p3^2;
sbit key2=p3^3;
sbit key3=p3^4;
(2)关键驱动过程
按键识别的一般流程如下:I/O口写“1”→判断某个按键是否被按下→延时摇动→确定键值→等待按键被抬起→执行按键功能。按键驱动中定义了两个静态变量“ts”和“kv”,分别用于延迟去抖和存储键值。
(3)延迟去抖
静态变量“ts”用于延迟去抖。在定时器中断服务程序中,每1毫秒执行一次按键驱动程序。当按下一个键“ts”并添加1时,如果没有按下一个键,它将被清除。如果键被连续按下20毫秒,当键驱动器被连续执行20次时,检测到键被按下。此时静态变量“ts”累计到20,可以确认按键被有效按下。
为了防止按键保持按下时“ts”累积溢出,可以将“ts”的值保持在20或者大于20的某个值,比如21。
(4)取键值
确认某个键被按下后,可以通过读取该键的I/O端口状态来获取键值。为了读取P3.2、P3.3、P3.4的管脚状态,屏蔽P3口其他管脚的影响,读取值可以逐位或高达11000111b(0x E3)后发送给静态变量“kv”。
静态变量“kv”存储该键的键值,在没有按下任何键或抬起键后,kv的值为0。按下启动键时Kv = 111110111b(0x FB),按下复位键时Kv = 1165448。当按下暂停/开始键key3时,KV = 11011111b(0x ef)。
(5)执行键功能
当按键被抬起后第一次执行按键驱动时,静态变量“kv”保存按键被按下时最终得到的键值,键值作为参数调用按键执行器“act key(kV);”可以执行按键功能。通话结束后,kv值立即清零,以确保按键功能执行一次。驱动程序代码如下:
void键()
{
静态无符号字符kv = 0;
静态无符号字符ts = 0;
key 1 = 1;key 2 = 1;key 3 = 1;
如果(!(key 1 & amp;key2 & amp按键3))
{
ts++;
if(ts & gt;= 20)ts = 20;//有一个键被按下。
如果(ts==20)
kv = iokey | 0xe3//获取键值
}
其他
{//没有按下或抬起任何键。
act key(kv);
ts = 0;
kv = 0;
}
}
函数actkey(kv)用于根据键值“kv”执行相应的操作。当“kv”等于0xFB时,表示启动键key1被按下,函数actkey(kv)将全局变量act赋值为“1”。当“kv”等于0xF7时,表示复位键key2被按下,函数actkey(kv)将全局变量“time”复位为“30”。当“kv”等于0xEF时,表示暂停/开始键被按下,函数actkey(kv)反转全局变量act。每按一次按钮,全局变量“t”就会被清零,这样每当定时器复位或启动时,进入计时中断的次数就会从0开始计数,否则第1秒计时不准。程序代码如下:
void actkey(无符号字符k)
{
开关(k)
{
case 0x FB:act = 1;t = 0;打破;
案例0xf7:时间= 30;t = 0;打破;
case 0x ef:act = ~ act;t = 0;打破;
}
}
四。结束语
本文在编程过程中用面向对象的编程思想封装了两个LED数码管和三个独立的按钮。在定时中断服务程序中调用它的驱动程序时,程序员只需要操作它的接口:数组“led_str[2]”和函数“actkey(unsigned char k)”,就可以改变函数,不需要直接对硬件编程,增强了软件的通用性和可移植性。