非常精简的NEC红外解码程序,适合程序存储空间低的单片机(C语言)
注意:之所以程序精简,是因为解码NEC协议时只计算协议中的高电平时间,不去计算低电平时间。对应的,可能会出现未知干扰波造成解码失败。
解码之前,我们先来熟悉一下NEC协议:
1、NEC协议载波:38khz
2、NEC编码格式为:引导码+8bit用户码+8bit用户反码+8bit数据码+8bit数据反码+重复码
3、NEC协议格式:
上图是一个完整的波形,其中每隔110ms发送一个重复码。
4、对应单片机解码需要用到的:
知道这些我们就可以开始解码了。(如有错误,请高手指出 ^_^ ^_^)
/* 寄存器定义 */
uint8_t IRHigh; /* 计数IR脚高电平时间 */
uint8_t IRReceiveCnt; /* IR接收数据计数 */
uint16_t UserCodeVal; /* 用户码 */
uint16_t DataCodeVal; /* 数据码 */
uint32_t DecodeVal; /* 32位数据 用户码+用户反码+数据码+数据反码 */
/* 位定义 */
#define IR_OK UserFlag.0 /* 解码完成时置一 */
#define IR_START_SIGNAL UserFlag.1 /* 红外解码引导码 检测到引导码置一 */
#define IR_PIN_START UserFlag.2 /* IO电平状态标志 */
/* 宏定义 */
#define USER_CODE 0x10ED /* 用户码 校验数据 */
/*******************************************************************************************
* 简易的NEC红外解码程序
* 1.此函数只是粗略的检测NEC协议中的高电平时间
* 2.此函数通过判断IO口状态+定时器扫描的方式完成的
* 3.此函数非常精简 用应广XY_IDE编译出来的文件只占79个程序空间 非常适合程序空间小的单片机
* 4.此函数解码是依据MSB优先传输,正好和NEC相反(LSB优先传输),特此注明
* 5.此函数没有对解码出来的数据进行校验 (数据码+数据反码=0xff 用户码+用户反码=0xff )
****声明:此函数仅作为参考程序 如需商业使用 还请自行验证
****验证平台:应广XY150C单片机+标准NEC协议遥控器
********************************************************************************************/
void IRDecode(void){ /* 此函数 100us扫描一次 */
if(!IR_OK){ /* 解码完成为1 */
if(IR_PIN_START){
if(!IR){ IR_PIN_START = 0; } /* 判断引脚电平状态 下降沿 */
if(IRHigh<49){ IRHigh++; } /* 计时IR脚高电平时间 */
}
else{
if(IR){
IR_PIN_START = 1; /* 判断引脚电平状态 上升沿 */
if(IR_START_SIGNAL){ /* 检测到引导码 可以开始解码 */
if(IRHigh>=13 && IRHigh<=19){ /* 数据1 1.7ms高电平 */
IRReceiveCnt++; /* 接收的信号次数计数 */
DecodeVal<<=1;
DecodeVal++; /* 将数据存入 接收数据寄存器中 */
}
else if(IRHigh>=4 && IRHigh<=8){ /* 数据 0 0.56ms高电平 */
IRReceiveCnt++; /* 接收的信号次数计数 */
DecodeVal<<=1; /* 将数据存入 接收数据寄存器中 */
}
else{
IR_START_SIGNAL = 0; /* 错误信号 复位解码状态 */
IRReceiveCnt = 0;
}
if(IRReceiveCnt==32){ /* 32个信号为一个周期 16位用户码+16位数据码 */
UserCodeVal = DecodeVal>>16; /* 取用户码 */
DataCodeVal = DecodeVal; /* 取数据码 */
if(UserCodeVal == USER_CODE){ /* 校验用户码 */
IR_OK = 1; /* 解码完成 */
}
IR_START_SIGNAL = 0;
IRReceiveCnt = 0;
}
}
if(IRHigh>=44){ /* 高电平信号4.4ms-4.8ms 为引导码 */
IRReceiveCnt = 0;
IR_START_SIGNAL = 1;
if(IRHigh==49){IR_START_SIGNAL = 0;}/* 错误信号 复位解码状态 */
}
IRHigh = 0; /* 清除高电平时间计数 */
}
}
}
}