今天下午的时候,调试努力之下,终于把红外解码弄出来了。其实以前有次比赛的时候就已经用到了红外,只是那次用的是51单片机,用的是外部中断和延时检测脉宽来进行解码,因为51的时钟这些比较简单,所以解码很容易就正确了。但是现在换到了ARM7平台下,由于对它的不是很熟悉,怎么用普通语句实现精确延时对我来说是个难点。最后考虑用两个方案来实现红外的解码。方案一是用外部中断加定时器延时检测脉宽进行解码,但是结果并没有我想的那样美好,调试了半天也没有实现正确的解码,个人认为是任务节拍的影响,但是确实不知道该怎么修改,最后放弃方案一,改用方案二,用定时器捕获实现红外的解码,并最终实现。
LPC2103芯片带有定时器捕获,可以设置为下降沿,上升沿或双边沿捕获中断。因为结合到此款红外编码方式,所以采用下降沿进行捕获。定时器0因为用作了系统节拍定时器,所以我选择了定时器1的捕获。
定时器1进行如下的初始化。
void SetTimer(void) { T1TCR = 0x02; //关闭复位定时器1 T1PR = 10; //11分频,约1us计时一次(外设时钟11.0592MHZ) T1CCR = 0x06; //下降沿捕获并产生中断 T1IR = 0x10; //清除定时器1捕获0中断 T1TCR = 0x01; //开启定时器1 VICVectAddr1 = (uint32)Timer1_Handler; //中断向量相关设置 VICVectCntl1 = (0x20 | 0x05); VICIntEnable |= (1 << 5); }
void Timer1_Exception() { static uint32 tOld; //保存旧的下降沿捕获值 uint32 tNew; //保存新的下降沿捕获值 static i; OS_ENTER_CRITICAL(); T1IR = 0x10; //清除定时器1捕获0中断 tNew = T1CR0; tValue = tNew - tOld; //得到两次下降沿之间的差值 tOld = tNew; //以便下次中断处理 OSMboxPost(Msg,(void*)tValue); //发送消息邮箱,行为同步 OS_EXIT_CRITICAL(); VICVectAddr = 0x00; }
在检测脉宽任务里,我只需要根据测定脉宽与本来编码原有的脉宽进行比较判断,然后进行相关移位数据操作,得到数据码值。
因为我的遥控器有点不同,地址码与地址反码不互反,所以不能进行地址的判断,所以滤除掉了引导码与地址码,直接进行了数据码的处理。
只要数据码与数据反码取反相同,则调试LED闪烁一下。
当然我还没有具体知道遥控器按键对应的具体码制是多少,而且还没有检测到连发码,留待下次把码制通过串口发送到上位机进行显示。
这是检测脉宽任务的核心代码:
while (1) { OSMboxPend(Msg, 0, &err); //等待脉宽检测消息 if(tValue>2145 && tValue<2345) //进行脉宽检测 { ucTemp = 1; //逻辑1 } else if(tValue>1025 && tValue<1225) { ucTemp = 0; //逻辑0 } else if(tValue>13400 && tValue<13600) { ucCounter = 0; //引导码 usData0 = 0; usData1 = 0; flag = 1; } else { continue; } if(flag) //数据处理过程 { ucCounter++; if(ucCounter<16) { usData0 |= (uint16)ucTemp; usData0 <<= 1; } else if(ucCounter == 16) { usData0 |= (uint16)ucTemp; } else if(ucCounter < 32) { usData1 |= (uint16)ucTemp; usData1 <<= 1; } else if(ucCounter == 32) { usData1 |= (uint16)ucTemp; flag = 0; OSSemPost(Sem); //发送信号量,进行码制转换任务,我的任务只是简单的实现了判断解码是否成功。 } } }