51单片机定时器中断按键消抖(无延时)

单片机入门学习记录(二)

在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。按键的抖动对于人类来说是感觉不到的,但对单片机来说,则是完全可以感应到的,而且还是一个很“漫长”的过程,因为单片机处理的速度在“微秒”级,而按键抖动的时间至少在“毫秒”级。单片机如果在触点抖动期间检测按键的通断状态,则可能导致判断出错,即按键一次按下或释放被错误地认为是多次操作,从而引起误处理。因此,为了确保单片机对一次按键动作只作一次响应,就必须考虑如何消除按键抖动的影响。———————————————————————————(来自百度百科)

为了实现按键消抖通常有软件消抖和硬件消抖的方法。

软件消抖有采用delay()的延迟消抖,虽然代码简单,但是在函数执行时CPU无法执行其他指令,直到函数执行完毕,影响程序运行。

定时器消抖则是采用定时器中断的方法,把按键扫描程序放置在定时器中断中,可以使得扫描程序减少对于cpu的占用,但是会占用一个定时器,虽然不及硬件消抖但是对于软件消抖来说已是很高效的方法。因此采用的此方法。


通过定时器中断以5ms的速度扫描一次当前的按键值,中断程序时间设置如下,

void int_time0() interrupt 1
{
    TH0=(65536-5000)/256;
    TL0=(65536-5000)%256;
    i++;
    if(i>3)
        i=0;
    key();
}

key_flag 为按键是否按下的标志位,其初始化为0。当key按下为0,high开始加一,只有按键值被定时器扫描到2次即持续为10ms以上时,判定key0按键确实按下了,key_flag置为1。开始松手检测,检测key0为1的时间达到10ms以上时,判定key0按键是完全松开,到此为一次完整的按键动作。所以P2的状态值改变。(下面程序为单按钮示例,多个按钮可以通过放置多个标志位来实现相同效果)

void key()
{
    if(key0==0&&key_flag==0)    //按键按下
    {
        high++;
        if(high>1)        //按下消抖
        {
            high=0;
            key_flag=1;
        }
    }
    else if(key0==1&&key_flag==1)    //松手检测
    {
        low++;
        if(low>1)        //松手消抖
        {
           P2=~P2;        //状态反转
            key_flag=0;
        }
    }
}

多按钮示例如下

    if(key0==0&&key_flag1==0)    //按键按下
    {
        high1++;
        if(high1>1)        //按下消抖
        {
            high1=0;
            key_flag1=1;
        }
    }
    else if(key0==1&&key_flag1==1)    //松手检测
    {
        low1++;
        if(low1>1)        //松手消抖
        {
            key_state1=~key_state1;
            key_flag1=0;
        }
    }
    if(key1==0&&key_flag2==0)        //按键按下
    {
        high2++;
        if(high2>1)        //按下消抖
        {
            high2=0;
            key_flag2=1;
        }
    }
    else if(key1==1&&key_flag2==1)        //松手检测
    {
        low2++;
        if(low2>1)        //松手消抖
        {
            key_state2=~key_state2;
            key_flag2=0;
        }
    }
### 单片机按键使用定时器实现方法 在嵌入式系统中,单片机常用于实现各种功能,其中包括定时器时钟的功能[^1]。针对按键动问题,可以采用定时器中断的方式进行有效的处理。 #### 定时器中断方式的优点 相比于传统的`while`死循环检测松手的方法,这种方法不会使程序陷入长时间等待的状态,从而节省了CPU资源,并提高了系统的实时性能[^3]。具体而言,当检测到按键按下事件触发外部中断后,启动定时器开始计数,在经过一定时间间隔(通常为几十毫秒)之后再检查按键状态;如果在这段时间内按键保持按下的状态不变,则认定这是一次有效按键操作[^4]。 #### 实现流程 - 初始化阶段设置好相应端口作为输入模式连接至物理按键; - 配置定时器参数使其能够满足所需延时时长的要求; - 编写中断服务例程ISR用来响应由按键引起的外部中断请求; - 在ISR内部开启定时器并重定向其溢出回调函数指向自定义的去逻辑处理部分; - 当定时器到期时重新评估当前键位情况以决定是否真正发生了点击行为。 以下是基于上述思路的一个简单C语言代码片段展示: ```c #include <reg52.h> sbit KEY = P3^0; // 假设按键接到了P3.0脚上 void Timer_Init(void); void Key_Scan(void); unsigned char flag; // 主函数 void main() { EA = 1; EX0 = 1; /* 开启外部中断 */ IT0 = 1; /* 设置下降沿触发 */ while (1){ if(flag == 1){ // 执行按键后的其他操作... flag = 0; } } } // 外部中断0的服务例程 void Ext_Int_0() interrupt 0 { TH0 = 0xFC; TL0 = 0x18; // 设定初值, 计算得到约等于20ms TR0 = 1; // 启动T0 } // T0中断服务例程 void Time_ISR() interrupt 1 { TR0 = 0; // 关闭T0 if(KEY==0) // 再次确认按键确实处于低电平 flag=1; // 表明已经完成了一次完整的按键动作 } ``` 此段代码展示了如何配置定时器以及编写必要的中断服务程序来达到按键的效果。需要注意的是实际应用中的细节可能会有所不同,比如具体的寄存器地址、初始化数值等都需要根据所使用的单片机型号查阅官方文档获取准确信息[^5]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值