单片机如何设计防抖动程序(源代码),单片机高阻态怎样克服?
经检测不到那个事件了。为了避免这种情况的发生,我们要尽量缩短 while(1)循环一次所用的时间,而需要进行长时间延时的操作,必须想其它的办法来处理。
那么消抖操作所需要的延时该怎么处理呢?其实除了这种简单的延时,我们还有更优异的方法来处理按键抖动问题。举个例子:我们启用一个定时中断,每 2ms 进一次中断,扫描一次按键状态并且存储起来,连续扫描 8 次后,看看这连续 8 次的按键状态是否是一致的。8 次按键的时间大概是 16ms,这 16ms 内如果按键状态一直保持一致,那就可以确定现在按键处于稳定的阶段,而非处于抖动的阶段,如图 8-12。
图 8-12 按键连续扫描判断
假如左边时间是起始 0 时刻,每经过 2ms 左移一次,每移动一次,判断当前连续的 8 次按键状态是不是全 1 或者全 0,如果是全 1 则判定为弹起,如果是全 0 则判定为按下,如果0 和 1 交错,就认为是抖动,不做任何判定。想一下,这样是不是比简单的延时更加可靠?
利用这种方法,就可以避免通过延时消抖占用单片机执行时间,而是转化成了一种按键状态判定而非按键过程判定,我们只对当前按键的连续 16ms 的 8 次状态进行判断,而不再关心它在这 16ms 内都做了什么事情,那么下面就按照这种思路用程序实现出来,同样只以K4 为例。
#include
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit KEY1 = P2^4;
sbit KEY2 = P2^5;
sbit KEY3 = P2^6;
sbit KEY4 = P2^7;
unsigned char code LedChar[] = { //数码管显示字符转换表
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
bit KeySta = 1; //当前按键状态
void main(){
bit backup = 1; //按键值备份,保存前一次的扫描值
unsigned char cnt = 0; //按键计数,记录按键按下的次数
EA = 1; //使能总中断
ENLED = 0; //选择数码管 DS1 进行显示
ADDR3 = 1;
ADDR2 = 0;
ADDR1 = 0;
ADDR0 = 0;
TMOD = 0x01; //设置 T0 为模式 1
TH0 = 0xF8; //为 T0 赋初值 0xF8CD,定时 2ms
TL0 = 0xCD;
ET0 = 1; //使能 T0 中断
TR0 = 1; //启动 T0
P2 = 0xF7; //P2.3 置 0,即 KeyOut1 输出低电平
P0 = LedChar[cnt]; //显示按键次数初值
while (1){
if (KeySta != backup){ //当前值与前次值不相等说明此时按键有动作
if (backup == 0){ //如果前次值为 0,则说明当前是弹起动作
cnt++; //按键次数+1
if (cnt 》= 10){ //只用 1 个数码管显示,所以加到 10 就清零重新开始
cnt = 0;
}
P0 = LedChar[cnt]; //计数值显示到数码管上
}
//更新备份为当前值,以备进行下次比较
backup = KeySta;
}
}
}
/* T0 中断服务函数,用于按键状态的扫描并消抖 */
void InterruptTImer0() interrupt 1{
//扫描缓冲区,保存一段时间内的扫描值
staTIc unsigned char keybuf = 0xFF;
TH0 = 0xF8; //重新加载初值
TL0 = 0xCD;
//缓冲区左移一位,并将当前扫描值移入最低位
这个算法是我们在实际工程中经常使用按键所总结的一个比较好的方法,介绍给大家,今后都可以用这种方法消抖了。当然,按键消抖也还有其它的方法,程序实现更是多种多样,大家也可以再多考虑下其它的算法,拓展下思路。
单片机高阻态是什么意思
在一个系统中或在一个整体中,我们往往定义了一些参考点,就像我们
- FPGA的DSP性能揭秘(06-16)
- 基于单片机通用引脚的软件UART设计(10-16)
- 分时操作系统思想在单片机中的具体应用 (10-30)
- 基于AT89C51+DSP的双CPU伺服运动控制器的研究(05-26)
- 关于RTX51 TINY的分析与探讨(05-30)
- 基于MC9S12DGl28单片机的智能寻迹车设计(04-03)