您的位置:首页 > 其它

一个遥控解码程序说明实际NEC码过程

2011-08-27 22:55 169 查看
#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•••的差别,一般情况下两者是可以通用的,但后者有个缺点是没有出口,一旦出现两个都不符合的值出现,将没有任何子程序段处理,在编译时会警告某些后面用到的参数在子程序段中没有初始化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: