本文接上篇繼續分析《幾種比較流行和成熟的紅外解碼程序做一下分析和總結1》:http://www.zg4o1577.cn/mcu/3320.html
下面說一說第二種過濾重復碼的方法,(這個方法是老板告訴我的,呵呵,不解釋)廢話不多說,直接上程序:
/*-----------------------------------------------------------------------------------------
定時器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,算法就是這樣的,不過和上面的那個程序相比這個程序沒有上面的那個好,第一個是這個時間如果設置的太短的話,過濾的作用,時間設置的太短,如果這個時間小于兩個重復之間的時間間隔那會就會再次使能中斷的接收,從而把原來的數據覆蓋掉,導致程序的出錯.如果這個時間設置的太長,那個一次按鍵按下去又得等待十年的時間才能再次開啟紅外的接收,是不是很坑爹啊。。,即使這個時間設置的恰到好處,也還是有一個時間的延遲的,相比上面的那個沒有時間延遲的程序還是有一點瑕疵啊!所以說上面那個程序,也就是我編的那處程序才是最好的算法和程序.