/*-----------------------------------------------------------------------------------------
定时器0中断处理
-----------------------------------------------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
irtime++; //用于计数2个下降沿之间的时间,256us进一次定时器中断
if(irtime>=1000)//irtime>=1000说明按键已经松天有1000*256=256ms了,故可以使能红外接收功能
{
ir_flag=0;//使能红外接收功能
}
}
/*-----------------------------------------------------------------------------------------
外部中断0中断处理
-----------------------------------------------------------------------------------------*/
void EX0_ISR (void) interrupt 0 //外部中断0服务函数
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位
if(irtime<=54&&irtime>=50)//接收到引导码 TC9012的头码,9ms+4.5ms
{
i=0;
}
if(ir_flag==1)
{
irtime=0; //清零计数器
return;
}
if(ir_flag==0)
{
irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;//清零irtime变量(老板习惯叫做寄存器)
i++;//数组下标自增1
if(i==33)
{
irok=1;//接收完33个红外数据
i=0;//数组下标清零
ir_flag=1;//失能红外接收功能
}
}
}
下面研究第二种红外解码的程序,这个程序没有用到任何中断,非常有意思啊,直接上源码.不解释.
/*----------------------------------------------------------------------------------------------------
红外解码处理函数
----------------------------------------------------------------------------------------------------*/
void ir(void)
{
if(ir_check_flag==1)
{
ir_check_flag=0;
if(PB.0==1)
{
if(irisH_bit==0)
{
irisH_bit= 1;
//这里可以添加上升沿到时时,做相应的处理
}
}
else
{
if(irisH_bit==1)
{
irisH_bit= 0;
if(irtime<=110&&irtime>=102) //引导码TC9012的头码,9ms+4.5ms
{
ramaddr1= irdata;
num= 0;
ir_en_flag=0;
}
if(ir_en_flag==1)
{
irtime=0; //如果是重复码就将irtime清零,然后退出函数
return;
}
if(ir_en_flag==0)
{
*ramaddr1= irtime;
ramaddr1++;
irtime= 0;
num++;
if(num==33)
{
irok=1; //32个数据全部存储完毕,一帧数据接收完毕
num=0;
ramaddr1= irdata;
ir_en_flag=1;
}
}
}
}
irtime++;
}
else
{
return;
}
}
分析一下这个程序的算法,其思路类似于原来中断函数的方法,也是记录两个下降沿之间的时间,并将其存入33个元素的一个数组中,数组的第一个位置存入的是那个**的引导码,后面的32个位置存入的是32个红外编码.这个算法关键的一点就是那个irisH_bit位变量的作用.那个位变量是用来记录边沿的,无论是下降沿还是上升沿都能记录,这个记录的作用就是只能使相关的处理只在相应的上升沿还是下降沿作用一次.这个函数每128us扫描一次.每128us计数器irtime增加一次.先来分析程序运行时的情况,当没有下降沿的时候,一直是高电平一直执行if(PB.0==1)下面的语句irtime一直做叠加的操作.当加到最大值时又变为0做新一轮的叠加操作.这个是没有意义的,等到第一个下降沿到来的时候进入else语句由于是第一个下降沿那个这个irtime就是随机的了,这时ir_en_flag=0,因为是初始化时的值,下面分两种情况来说明这时的情况,如果这个irtime的时间刚好在引导码的区间,那么就会清零num,数组下标清0然后进入if(ir_en_flag==0)语句将这个值取入数组的第一个位置,然后下一个下降沿来到了,这时这个时间就是实实在在的引导码的时间,同样会进入if(irtime<=110&&irtime>=102)那一个分支,这时将数组下标清零,同时进入下一条分支语句if(ir_en_flag==0),这时将先前存入数组的每一个元素覆盖掉,那个也就不存在了,而后是32个红外数据的存入,这里有一个值得注意的问题在第32个红外数据接收完成之后,会有一个下降沿,这个是不属于那32个数据的电平.是多出来的一个下降沿,当这33个数据接收完成的时候,会关断数据的存储,只有下一次再接收到引导码才会再次开启数据的存储功能,这样做可以有效的把后面的重复码干掉,这个程序的关键仍然是那个引导码的时间只有这个时间足够准确,足够狭窄才能和那个重复码区别开来.
下面提供另一个过滤重复码的方法,直接上源代码,不解释.
/*----------------------------------------------------------------------------------------------------
红外解码处理函数
----------------------------------------------------------------------------------------------------*/
void ir(void)
{
if(ir_check_flag==1)
{
ir_check_flag=0;
if(PB.0==1)
{
if(irisH_bit==0)
{
irisH_bit= 1;
}
}
else
{
if(irisH_bit==1)
{
irisH_bit= 0;
if(irtime<=110&&irtime>=102) //引导码 TC9012的头码,9ms+4.5ms
{
ramaddr1= irdata;
num= 0;
}
if(ir_en_flag==1)
{
irtime=0; //如果是重复码就将irtime清零,然后退出函数
return;
}
if(ir_en_flag==0)
{
*ramaddr1= irtime;
ramaddr1++;
irtime= 0;
num++;
if(num==33)
{
irok=1; //32个数据全部存储完毕,一帧数据接收完毕
num=0;
ramaddr1= irdata;
ir_en_flag=1;
}
}
}
}
irtime++;
if(irtiem>=10000) //如果长时间没有按下摇控的按键,就重新接收下一帧数据
{
ir_en_flag=0;
}
}
else
{
return;
}
}
这个程序去除重复码的方法就是老板告诉我的去除重复码的方法.这里一帧新的数据的接收使能是松开按键的时间超过128ms,算法就是这样的,不过和上面的那个程序相比这个程序没有上面的那个好,第一个是这个时间如果设置的太短的话,过滤的作用,时间设置的太短,如果这个时间小于两个重复之间的时间间隔那会就会再次使能中断的接收,从而把原来的数据覆盖掉,导致程序的出错.如果这个时间设置的太长,那个一次按键按下去又得等待十年的时间才能再次开启红外的接收,是不是很坑爹啊!!!,即使这个时间设置的恰到好处,也还是有一个时间的延迟的,相比上面的那个没有时间延迟的程序还是有一点瑕疵啊!所以说上面那个程序,也就是我编的那处程序才是最好的算法和程序.
|
|