#define WD_END (5u+1u) // 5ms
#define RM_OFTM 60u // 20ms
#define RM_OFTM_R 100u // 100ms
/*以下的时序值都经过特殊处理*/
#define RC_HEADER0 (13300000ul/RC_CLK) //13.3MS
#define RC_HEADER1 (13700000ul/RC_CLK) //13.7MS
#define RC_REPEAT0 (11050000ul/RC_CLK) //11.05MS
#define RC_REPEAT1 (11450000ul/RC_CLK) //11.45MS
#define RC_CODE1 (2250000ul/RC_CLK) //2.25MS
#define RC_CODE1_GOSA ( 200000ul/RC_CLK) //0.2MS
#define RC_CODE0 (1125000ul/RC_CLK) //1.125MS
#define RC_CODE0_GOSA ( 100000ul/RC_CLK) //0.1MS
#define RC_CODE_0_1 (2000000ul/RC_CLK) //2 MS
对以上定义补充说明:程序中RC_CLK是 1185ul,这是因为分频运算后1/27M×32=1.185(周期乘以MCU位数,注意单位跟M对应的是US)。这是表示一个CLK是对应1.185微秒,由于遥控计时器是对RCLK进行计数,所以要有一个转换,M×RCLK(对应的时间)=13.3MS,即M=13.3M/RCLK=13.3×1000US/1.185US得对应的参考值。
/*定义解码所需的标志*/
static U32 InputData; //转储数据
static U8 rcv_header = WRONG; //解出头码标志
static U8 rcv_repeat = WRONG; //解出重发标志
static U8 BitCount; //位计数器
static U8 RcOffTimer; //遥控发码的剩余时间
U8 OneCodeTime;
void remocon_initial (void)
{
/*初始化IR相应的寄存器*/
BitCount = 0;
}
#pragma INTERRUPT remocon_edge //边沿中断触发函数,由电平跳变即执行
void remocon_edge (void)
{
/*在IR寄存器检测正常的情况下,继续执行*/
U16 pls_cnt = IR_MFTCMPRLD;
if( (RC_HEADER0 <= pls_cnt) && (pls_cnt <= RC_HEADER1) )
{
//Header Pulse,判断头脉冲,由于反向后IR PIN默认是高电平,该寄存器主要用来
rcv_header = TRUE; //获得一次由低到高的跳变时间,NEC默认是13.5MS,13.3<13.7
//由于接下来就是数据码,所以不需要时延RcOffTimer。
}
Else if( (RC_REPEAT0 <= pls_cnt) && (pls_cnt <= RC_REPEAT1) )
{
//Repeat Pulse,同理用来检测重发码,NEC标准为11.5MS,必须处于RC_REPEAT0
rcv_repeat = TRUE; //与RC_REPEAT1之间,即视为识别
RcOffTimer = RM_OFTM_R; //由于重发后相邻的一次脉冲在100MS之后,所以有//必要延时,避免重复检测。
}
Else if( rcv_header == TRUE ) //头码判断出来之后
{
if( BitCount < 32 ) //位长32位是标准,如果未到,继续检测完。
{
if((pls_cnt>=(RC_CODE0-RC_CODE0_GOSA))&&((RC_CODE1+RC_CODE1_GOSA) >= pls_cnt))
{
InputData >>= 1; //需处理新的一位,将以前的数据右移,注意发送顺序//和存储过程是反向的。
if ( pls_cnt >= RC_CODE_0_1 ) //如果时延大于2MS,足可以判定该次接//收的是1
{
InputData |= 0x80000000;//将最高接收位置1,说明该次读出的是1
}
BitCount++; //位计数器加1
RcOffTimer = RM_OFTM; // RcOffTimer的作用很奇特,其实在每解出一//个位后,该值被重置。当解出最后一个BIT后,该值才不再改变,被后//面的 //1MS处理函数处理消耗完剩下的时间,再集中判断处理。该值不一//定很准,因为跟之前的01数目有关系,所以只能提供大概值。
}
}
OneCodeTime = WD_END; //一次解码过程完成,做个标记值,供后面消耗时间再//判断
}
}
Void remocon_1ms (void) //该函数处在一个1MS的控制台中,循环执行。其中的两个子///////过程一个用来处理单发,一个处理重发。
{
if( OneCodeTime != 0 ) //在一次所有的码发完之后,OneCodeTime值固定下来,
{
OneCodeTime- -; //延迟稳定6MS之后开始解数据
if( OneCodeTime == 0 )
{
if( BitCount >= 32 ) //在完整接收和正确发码的情况下,最后一次边沿触发//完后,BitCount是32,当然有多32位的情况下,会忽略掉后面的(偶尔)
{
RcOffTimer = RM_OFTM; //进入该判断,表示正确接收开始解码,其后// RcOffTimer是为了消耗掉一次发码后剩余的时间
if( (InputData & 0x0000FFFFu) == CUSTOMER_CODE )//如果客户码是//匹配的,注意顺序我们从示波器上读的值是从右往左存,所以客户码转//成16进制时从高位往低位组合。
{
if( (U8)((((InputData & 0xFF000000) ^ ((InputData & 0x00FF0000u) << 8)) >> 24) ) == 0xFF ) //如果数据码和数据码的反码相匹配,满足异或为1
{
RcData = (U16)((InputData & 0x00FF0000u) >> 16); //真正////解出了一个码值
InputData = 0; //清空转储变量
}
}
}
BitCount = 0; //不管有没有正确解出数据,在一次完整的发出数据后,要//清空BitCount和rcv_header,表示当前该次解码结束,如果<32,无效忽略,//是一种容错机制
rcv_header = WRONG;
}
if( RcOffTimer != 0 ) //用于消耗掉剩余时间
{
RcOffTimer--;
if( RcOffTimer == 0 )
{
if( rcv_repeat == TRUE ) //如果在耗时这段时间内(显然比重发间隔要//长),重发键仍然按着,RcData仍然有效。
{
rcv_repeat = WRONG; //rcv_repeat清空,判断下一个重发耗时间隔//是否有效
RcOffTimer = RM_OFTM_R;
}
Else //如果时间耗完后,rcv_repeat仍然0,说明没有连按,清RcData
{
RcData = NP;
}
}
}
}//此处有误
需要注意的是,NEC的大体过程是上面,但在时延上(不一定是那些时间表示01),数据位个数上(不一定是32位)。需要作些特殊处理。If•••else•••和if •••else if•••的差别,一般情况下两者是可以通用的,但后者有个缺点是没有出口,一旦出现两个都不符合的值出现,将没有任何子程序段处理,在编译时会警告某些后面用到的参数在子程序段中没有初始化。