2014年3月20日

CC2530开发板基础实验(2)—— 按键的轮询及中断

我的开发板上只有一个按键S2和一个5向Joystick。Joystick涉及到ADC,暂时不去弄了。对于按键的处理可以采用两种方式:轮询和中断。轮询是一种低效的方式,CPU不断的访问每一个可能产生输入信号的管脚,如果有信号输入,那就做出相应的处理,否则访问下一个输入管脚。而中断方式则类似于C#里的事件绑定、Java里的观察者模式,当输入管脚、时钟等产生一个中断信号,CPU会中止当前正在处理的事务,转去执行中断源的程序。待处理完中断再继续之前中止的事务。这里我用的是“类似”,即它并不是一种多线程模式,如果在执行中断源的响应程序的过程中,又有新的中断,那么后产生中断会等待当前中断源的响应程序执行完毕才会执行。这个等待队列也是有限的,似乎只能容纳一个等待的中断源。

首先讲一下轮询模式。

轮询模式下,需要将按键的管脚设置为普通I/O口,输入模式。我的按键在P0.5,所以把P0SEL和P0DIR的第5位都置0:

#define S2 P0_5
P0SEL &= ~0x20;
P0DIR &= ~0x20;

然后在main函数里:

void main(void){
  initLed();  // 初始化所以的LED灯,并全部处于熄灭状态,此处略去具体实现
  P0SEL &= ~0x20;
  P0DIR &= ~0x20;
  while(1){
    if (scanS2()){   // 按键按下则改变LED状态
      flashLed();    // 闪烁所有的LED灯,此处略去具体实现
    }    
  } 
}

scanS2()这个函数是用来检测按键S2是否被按下并被释放,即在被释放后才会执行flashLed()。

scanS2()的实现如下:

uchar scanS2(void){
    if (S2 == 0){ //0为按下,1为未按下
      delay(10);  // 延时去抖
      if (S2 == 0){
        while(!S2); //松手检测
        return 1;     //有按键按下
      }
    }
    return 0; //无按键按下
}

轮询模式到这里就结束了,代码很少。下面是中断模式

中断模式需要查阅CC2530的数据手册,如图,需要将PICTL对应位上置0或1(端口触发中断模式,上升沿、下降沿,由图可知,两种方式都可以触发,但CC2430的图CC2530不同,只能采取一种方式触发)、P0IEN(P0口各位中断使能)的对应位置1;P0IE(P0口中断使能)、以及EA(总中断使能)设为1。

红圈部分为总中断使能EA

然后是实现中断处理函数:

#pragma vector = P0INT_VECTOR    
__interrupt void P0_5_KeyPress(void) 
{ 
  if((P0IFG & 0x20) == 0x20){  //P0IFG的第5位为1,即P0_5触发了中断
    flashLed(500); 
    // 响应完毕,最后清除标志位
   
     P0IF  = 0;        //清P0的中断未决标志(0为无中断未决)
    P0IFG &= ~0x20;    //清P0_5的中断标志
  }
} 

其中前两行的格式固定,必须前后相接,唯一可以改动的就是第二行的函数名称,我这里是P0_5_KeyPress,这个名字是可以改的。从这个名字可以看出,一旦S2被按下,就会发出中断信号,即使按键还没有被释放。而第四行里,判断是否为S2产上的中断用了if((P0IFG & 0x20) == 0x20,这样可以准确地判断是否是由P0_5产生的中断。而我看的教程里,直接用P0IFG > 0 来判断,这种做法是存在误判的可能的。

当执行完中断处理的程序后,需要清理掉相关的标志位,注释中已经写明了,同样只动P0IFG的第5位,别的不要碰。

使用中断方式,main()函数里也很简练:

void main(void){
  initLed();
  P0IEN |= 0x20;   // P0.5 设置为中断方式 1:中断使能
  PICTL |= 0x20;   // 下降沿触发   

  P0IE   = 1;    // 允许P0口中断; 
  EA     = 1;    // 打开总中断
  while(1); 
}

至此,按键的两种模式就讲完了。实际上,可以将这些LED、按键的初始化操作封装到几个函数中,之后在开发中只要引入头文件就可以直接调用了,十分方便。虽然这一工作已经有人完成,并且可以很容易地在网上找到这些代码,但对于新手来说,这样的“重新发明轮子”的工作还是值得去做一下的。

没有评论:

发表评论