因为红外遥控要占用的系统中断时间可能超过了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;
....
}
比较如果有合适的, 就播放对应的字符串.