×
单片机 > 单片机程序设计 > 详情

基于MSP430F5529的按键消抖问题

发布时间:2020-08-21 发布时间:
|

注:板子:MSP430F5529 开发环境:CCSv5


上一篇博文发了按键中断的例程和详细的注释,但是好像把程序烧进单片机之后执行效果并不是很好:每按一次按键灯的状态不一定只改变一次,有时灯本来是亮的,按一次后还是亮的;或者按下去之后灯灭了,按键抬起来之后灯又亮了。


造成该现象的原因就是按键的抖动问题。

按键的抖动一般是机械性抖动,当开关断开或闭合时接触点处不会一下子接通也不会一下子断开,而是会产生轻微的抖动导致电路的多次接通和断开,这个过程大致会持续5ms-10ms。想像一下如果中断程序是瞬间完成的,那么接触点每抖动一下都会引起一次中断,所以就会引起按下按键后灯的状态改变次数是不确定的,也就是效果和我们的预期不一致;由于按下和抬起时都会有抖动产生,所以就会出现按下去灯灭,抬起来灯亮的情况。


知道了抖动产生的原因,我们就可以思考解决的办法了。


1、延时消抖

很显然如果中断的反应不要那么快,是不是就可以避免这个问题了呢?那么有一个办法就是把中断程序的执行时间延长,让中断执行的慢一点,这样在第一次触发中断后cpu去执行中断程序,当抖动引发的中断请求发出时中断标志位IFG已经被置位所以这些中断请求相当于被覆盖掉了,从而达到消抖的目的。

于是我们的中断程序为


#pragma vector = PORT2_VECTOR

__interrupt void Port_2 () {

__delay_cycles(10000);            //延时消抖 所传递参数为cpu周期

P1OUT |= BIT0;

}


似乎是可以的,设置按键下降沿触发中断,按下后避过抖动时间然后改变灯的状态,但是还有按键抬起呢?抬起时的抖动一样会触发中断,这时我们可以加一条语句


#pragma vector = PORT2_VECTOR

__interrupt void Port_2 () {

__delay_cycles(10000);            //延时消抖 所传递参数为cpu周期

if((P2IN & BIT1)==0) {

P1OUT ^= BIT0;

}

P2IFG &= ~BIT1;

}


判断延时后按键处于按下状态时才改变灯的状态,否则就不变。

如果想上升沿触发中断的话就改一下判断条件就好了。


2、利用定时器

还有一个办法,就是不用按键去触发中断,而是定时检测按键的状态。

当按键按下后,电平状态为 高—低—高,那么我们就去不停的检测按键的电平状态,若发现电平由高变低,那么改变灯的状态就好了。

利用定时器,每隔10ms左右(可调整)去检测按键电平,用两个变量分别记录上一次的状态和本次的状态,发现符合条件就改变灯的状态。

具体实现如下:


#include  

int main(void) {

    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

P1DIR |= BIT0;

P2DIR &= ~BIT1;


P2OUT |= BIT1;

P2REN |= BIT1;

TA0CTL |= TASSEL_1 + MC_1 + TAIE + TACLR;

TA0CCR0 = 32;

__bis_SR_register(LPM4_bits + GIE);

return 0;

}

#pragma vector=TIMER0_A1_VECTOR

__interrupt void TIMER0_A1_ISR() {

static unsigned char key_now=0;

unsigned char key_past=0;

key_past=key_now;

if(P2IN & BIT1) key_now=1;

else key_now=0;

if(key_now==0&&key_past==1) P1OUT ^= BIT0;

TA0CTL &= ~TAIFG;

}


关键字:MSP430F5529  按键  消抖问题 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP430F5529 上手小例程2