CC2541的任务与事件,以及红外捕捉.

因为红外遥控要占用的系统中断时间可能超过了80ms, 极有可能导致蓝牙断线, 特别是连续两次按键, 100%断线.

后来根据蓝牙技术群里的哥们提示, 觉得不能在一个中断中delay得太久, 只能用任务跟事件的情势来实现了.

首先原理是, 利用现有的SimpleBLEPeripheval的这个任务, 增加一个处理案件的事件.

#define SBP_CATCH_IRF_EVT   0x0008

接着写一个输入口的下降沿触发的中断:

volatile unsigned char readingISR=0;
#pragma vector = P0INT_VECTOR      
__interrupt void P0_ISR(void)   
{   
    key_nop();
    if(NOT_DISPLAYING==sysStatus)
    {
        if(Key_Check_Pin() == KEY_PRESS)   
        {         
        unsigned char IRCOM[7]={0,0,0,0,0,0,0};
        if(readingISR==0){
            readingISR=1;          
            readISROrigin(IRCOM);
            readingISR=0;
        }      
        }
    }  
    P0IFG &=~(1<<2);       //清除中断标志
    P0IF = 0;        //清除中断标志
    key_nop();
}


具体init的方法就不贴了.

readISROrigin(IRCOM)其实输入是没用的.

实际原本是在这个方法中捕捉输入的.

但是不是延时太长会断蓝牙么, 在这儿仅仅判断一下起始条件:

void readISROrigin(uint8* IRCOM)
{
    //unsigned char j,k,N=0;
    //EA = 0;
    disableP02Int();
    key_delay_140us(15);
    if (IRIN==1)
    {
        //EA =1;
        enableP02Int();
        return;
    }
    while (!IRIN)  //等变高       
    {key_delay_140us(1);}
    
    osal_start_timerEx(11, 8, 1);

}

红框的后半部分, 等升高, 具体的红外的协议, 就是一开始一个9.38ms的一个低电平, 然后一个4.24ms高电平, 表示开始, 具体多久我不管了, 没空.

总之捕捉到这个电平变换, 发送一个event, 这个event之前定义了是0x0008二进制数是从右边数第3个bit是1.

osal_start_timerEx(11, 8, 1);

其实正常的写法应该是用

osal_start_timerEx(simpleBLEPeripheral_TaskID, SBP_CATCH_IRF_EVT, 1);

最后内个1表示1ms后发消息.

然后就是在simpleBLEPeripheval.c里面处理event的方法里面, 增加对SBP_CATCH_IRF_EVT的响应.

uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{

....

 if(events & SBP_CATCH_IRF_EVT){
      uint8 ircom=ISR_BLANK_CODE;
      ircom=readISRP0_2();
      if(ircom==0){
          osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_CATCH_IRF_EVT, 1 );
     
      }else if(ircom==0xFF){
          osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_CATCH_IRF_EVT, 1 );   
          
      }else if(ircom!=ISR_BLANK_CODE){
          handleRemoteButtonPressed(ircom);
      }
      
    
      return (events ^ SBP_CATCH_IRF_EVT);
  }

...

}

先捕捉第1个字节:

   if(ircom==0){
          osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_CATCH_IRF_EVT, 1 );
     ..

接着捕捉第2个字节:

   }else if(ircom==0xFF){
          osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_CATCH_IRF_EVT, 1 );   
         

第3个字节:

 }else if(ircom!=ISR_BLANK_CODE){
          handleRemoteButtonPressed(ircom);
      }

第4个字节:

第4个字节不管了.

捕捉到第3个字节的时候, 就去比较是否是按键的红外编码:

void handleRemoteButtonPressed(uint8 code){
    if(NOT_DISPLAYING==sysStatus){
        switch(code){
        case RemoteButton1:
            sysStatus=DISPLAYING;
            playSentence(1);
        break;
        
        case RemoteButton2:
            sysStatus=DISPLAYING;
            playSentence(2);
        break;

....

}

比较如果有合适的, 就播放对应的字符串.

原文地址:https://www.cnblogs.com/Montauk/p/5920113.html