黄 华,李晓锋,曾小宝
(张家界航空工业职业技术学院,湖南 张家界 427000)
红外线是光谱中波长为0.76~1.5μm的一段不可见光,红外光波长短、方向性好,对复杂电磁环境不敏感,通常使用的红外发射器件(红外发光管)与红外接收器件(光敏二极管、三极管)的发光与受光峰值波长一般在0.8~0.94μm,二者的光谱正好重合,能够很好的匹配[1]。利用红外光的这种特点,实现点对点的直接数据传输,可以获得较高的传输效率及可靠性,因此广泛用于红外遥控系统。目前采用单片机实现红外解码已经得到普遍运用,但大多采用中断加延时等待的方法实现,但在实时系统中通常不能长时间地延时等待,这使得该方法使用范围受到限制。笔者研究使用赛元推出的低成本单片机SC92F8463B结合有限状态机实现红外解码,具有较少资源占用和高可靠性的特点。
SC92F8463B是一颗增强型的高速1T 8051内核工业级集成触控按键功能的Flash微控制器,指令系统完全兼容传统8051产品系列。SC92F8463B内部集成有16 Kbytes Flash ROM、1 Kbytes SRAM 、128 bytes EEPROM、最多26个GPI/O、13个IO可外部中断、3个16位定时器、11路12位高精度ADC、6路独立10位PWM、内部1%高精度高频12/6/2 MHz振荡器和4%精度低频128K振荡器、可外接晶体振荡器、一个UART,一个UART/SPI/IIC三选一通信口SSI。SC92F8463B具有非常优异的抗干扰性能和性能极好的触控按键性能,非常适合应用于各种使用场合的触控按键和主控控制,如大小智能家电和智能家居、物联网、无线通讯、游戏机等工业控制和消费应用领域。
不同公司在红外遥控中采用了不同的编码格式,其中比较常用的是NEC标准。遥控器采用频率为38 kHz、占空比为1/3的红外光发射编码信号,编码信号由引导码、客户码、客户反码、数据码和数据反码组成。引导码由9 ms的载波和4.5 ms的SPACE信号组成。客户码及客户反码16位、数据码及数据反码16位,共32位,客户码用于区别不同的红外遥控设备,防止不同机种遥控码的相互干扰,后16位为8位的操作码和8位的操作反码,用于核对数据是否接收正确,接收端依据数据码的值判断应该执行何种操作。NEC协议典型的编码脉冲如图1所示。
在编码信号中,逻辑1采用560μs的载波和1.69 μs的SPACE信号表示,逻辑0采用560μs的载波和560μs的SPACE信号组成,如图2、图3所示。
图1 NEC标准的红外码
图2 逻辑1的定义
图3 逻辑0的定义
NEC协议还规定,若按键超过108 ms仍未松开,将每隔108 ms发送一个Repeat Code信号,信号由9ms的起始码和2.5 ms的SPACE信号组成,如图4所示。
图4 Repeat Code的定义
本设计采用一体化红外接收头接收红外遥控信号,接收头检测到38kHz的载波信号后,将输出高电平,因此红外解码的关键是检查接收头输出引脚的电平变化,并识别信号高低电平持续时间。
本方案中使用SC92F8463B的外部中断检测引脚电平变化,在后台启动一个定时器用于计时。SC92F8463B的外部中断相对于传统51单片机的优点在于可以设置为下降沿、上升沿和双沿触发,在中断处理程序中,清0计时器,并改变触发边沿设置,在下一次触发中断时,计时器的计数值就是一个电平的持续时间。采用有限状态机进行红外解码时,需要根据红外遥控协议设计多个状态,每一个状态代表已经检测到某一个信号,在中断服务程序中,根据当前的状态和电平持续时间来判断是否协议规定时间,并转移到新的状态。
根据NEC的编码规范,笔者设计出如图5所示的红外解码状态图。图中IDLE_STATE状态代表空闲,没有检测到红外信号。下降沿触发中断,转移到RECEIVE 9MS LEADING状态,该状态代表已经检测到红外信号,并期待9ms的引导电平,RECEIVE 4.5 ms SPACE状态代表已经接收到9ms LEADING,期待4.5ms的SPACE信号,Receive 32bit Data状态作为一个过渡状态,进入到1、0 Identtify状态,判断SPACE的长度进而识别逻辑1或0,32bit识别完成后,回到IDLE_STATE状态,完成一次红外解码,设置标志变量,通知用户程序处理红外遥控命令[2]。状态图中也引入了RECEIVE Repaeat Code用于识别重复按键信号。
图5 红外解码状态图
根据状态图,可以较容易地实现红外解码的中断处理函数。关键代码如下所示,因为篇幅限制,所附代码中省略了部分状态的实现。代码中有几点值得特别说明,第一,每次中断通过取反INT1F、INT1R改变了中断触发的边沿;第二,电平持续时间是通过读取TH0、TL0实现的;第三,电平持续时间判断是将其与一个范围比较,以提高程序的抗干扰能力。
void irdecode_isr(void) interrupt 2
{
static unsigned char ir_receive_bits=0;
unsigned char i=0;
uint16_t interval=MAKEWORD(TH0,TL0);//捕捉两次中断之间的时间
TL0=0;TH0=0;//清零计数器,
INT1F^=(1<<0);//改变电平触发边沿
INT1R^=(1<<0);
switch(ir_decode_state)
{
case eIR_IDLE://此状态下,引脚为高电平,等待下降沿触发中断
ir_decode_state=eIR_LEADING_9MS;
break;
case eIR_LEADING_9MS:
if(interval>8000 && interval<10000){
ir_decode_state=eIR_LEADING_4MS5;
}else{
ir_decode_state=eIR_IDLE;
}
break;
...
case eIR_IDENTIFY_1or0:
i=ir_receive_bits>>3;
ir_receive_buffer[i]>>=1;
if(interval>1380&&interval<1980)
{//1.6785ms
ir_receive_buffer[i]|=0x80;
}
++ir_receive_bits;
ir_decode_state=eIR_32BIT_DATA;
break;
}
}
本红外解码方案采用有限状态机技术,避免了长时间的延时,有效地提高了系统的实时性;方案使用的硬件资源只有一个双沿触发的外部中断引脚和一个定时器资源,这在各种低成本单片机中都是标配硬件资源,可移植性强。