CC254x 中断+编码器(Rotary Encorder)

物联网时代, SOC的地位还是比较明显的。如果你只把CC254x 当一个蓝牙模块用, 那么你从成本上就OUT了。

经过最近的研究,终于把CC254x实现的硬中断+编码器捣鼓好了

首先配置硬中断, 对着寄存器手册, 分以下几步:

①将对应脚初始化为GPIO (PxSEL)

②将对应脚选择为输入 (PxDIR)

③将对应脚中断标志清除 (PxIF, PxIFG)

④设置触发边沿 (PxCTL)

⑤使能该端口中断(IEN2)

⑥使能该引脚中断(PxIEN)

⑦开启中断(EA = 1)

同时也可以通过P2INP设置上下拉还是三态输入, 具体看PDF《CC2540/41 System-on-Chip Solution for 2.4-GHz Bluetooth® low energy Applications》

然后编写对应的ISR程序

#pragma vector = P1INT_VECTOR
__interrupt void KEY1_ISR(void)
{
    //handle something here
    P1IFG = 0;
    P1IF = 0;
}

以上完成了中断的配置,接下来进行编码器程序的编写。

450px-Quadrature_Diagram.svg.png

AB相旋转编码器的原理不做赘述,这里找到了一种利用单中断进行计数的方案, 在某相开启双边沿中断, 在ISR中判断两相电平相等, 则加一,否则减一, 高效便捷。

这儿唯一有问题的是, CC254x不支持双边沿中断,那好办, 每次中断中切换边沿就可以了。使用异或操作  PICTL ^= BV(2); 进行边沿翻转, 全部代码如下:

PS: 使用HT1621 驱动的 6段LCD数码管显示数字

#include "ioCC2540.h"
#include "ht1621.h"

#define BV(bit) (1 << (bit))

long count = 0 ;
unsigned char NUM[]={0x7D,0x60,0x3E,0x7A,0x63,0x5B,0x5F,0x70,0x7F,0x7B,0x02}; 

void DelayMS(){
  for(int i=0;i<10000;i++){
  }
}

void InitKey(void)
{
  P1IFG = 0;
  P1IF = 0; // 中断标志位置 0
  PICTL |= BV(2); // 下降沿触发
  IEN2 |= BV(4); // 使能Port 1 的中断.
  P2INP |= BV(5);
  //P2INP |= BV(6);

  P1IEN |= BV(5); // 把P1.1 的中断功能打开

  EA = 1;
}
#pragma vector = P1INT_VECTOR     
__interrupt void KEY1_ISR(void)  
{
    PICTL ^= BV(2); // 下降沿触发
    if(P1_5 != P1_6)
      count++;
    else
      count--;
    
    P1IFG = 0;
    P1IF = 0;
}

int main( void ) 
{
  P1SEL = 0;
  P1DIR = 0x0F;
  Init_1621();
  InitKey();
  while(1){
    int  t = count;
    for(int i=0;i<6;i++){
      Write_1621_data(i, NUM[ t % 10]);
      t /= 10;
    }
    DelayMS();
  }
}

发表评论