本文接上篇繼續(xù)分析《幾種比較流行和成熟的紅外解碼程序做一下分析和總結(jié)1》:http://www.torrancerestoration.com/mcu/3320.html
下面說一說第二種過濾重復(fù)碼的方法,(這個(gè)方法是老板告訴我的,呵呵,不解釋)廢話不多說,直接上程序:
/*-----------------------------------------------------------------------------------------
定時(shí)器0中斷處理
-----------------------------------------------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
irtime++; //用于計(jì)數(shù)2個(gè)下降沿之間的時(shí)間,256us進(jìn)一次定時(shí)器中斷
if(irtime>=1000)//irtime>=1000說明按鍵已經(jīng)松天有1000*256=256ms了,故可以使能紅外接收功能
{
ir_flag=0;//使能紅外接收功能
}
}
/*-----------------------------------------------------------------------------------------
外部中斷0中斷處理
-----------------------------------------------------------------------------------------*/
void EX0_ISR (void) interrupt 0 //外部中斷0服務(wù)函數(shù)
{
static unsigned char i; //接收紅外信號處理
static bit startflag; //是否開始處理標(biāo)志位
if(irtime<=54&&irtime>=50)//接收到引導(dǎo)碼 TC9012的頭碼,9ms+4.5ms
{
i=0;
}
if(ir_flag==1)
{
irtime=0; //清零計(jì)數(shù)器
return;
}
if(ir_flag==0)
{
irdata[i]=irtime;//存儲(chǔ)每個(gè)電平的持續(xù)時(shí)間,用于以后判斷是0還是1
irtime=0;//清零irtime變量(老板習(xí)慣叫做寄存器)
i++;//數(shù)組下標(biāo)自增1
if(i==33)
{
irok=1;//接收完33個(gè)紅外數(shù)據(jù)
i=0;//數(shù)組下標(biāo)清零
ir_flag=1;//失能紅外接收功能
}
}
}
下面研究第二種紅外解碼的程序,這個(gè)程序沒有用到任何中斷,非常有意思啊,直接上源碼.不解釋.
/*----------------------------------------------------------------------------------------------------
紅外解碼處理函數(shù)
----------------------------------------------------------------------------------------------------*/
void ir(void)
{
if(ir_check_flag==1)
{
ir_check_flag=0;
if(PB.0==1)
{
if(irisH_bit==0)
{
irisH_bit= 1;
//這里可以添加上升沿到時(shí)時(shí),做相應(yīng)的處理
}
}
else
{
if(irisH_bit==1)
{
irisH_bit= 0;
if(irtime<=110&&irtime>=102) //引導(dǎo)碼TC9012的頭碼,9ms+4.5ms
{
ramaddr1= irdata;
num= 0;
ir_en_flag=0;
}
if(ir_en_flag==1)
{
irtime=0; //如果是重復(fù)碼就將irtime清零,然后退出函數(shù)
return;
}
if(ir_en_flag==0)
{
*ramaddr1= irtime;
ramaddr1++;
irtime= 0;
num++;
if(num==33)
{
irok=1; //32個(gè)數(shù)據(jù)全部存儲(chǔ)完畢,一幀數(shù)據(jù)接收完畢
num=0;
ramaddr1= irdata;
ir_en_flag=1;
}
}
}
}
irtime++;
}
else
{
return;
}
}
分析一下這個(gè)程序的算法,其思路類似于原來中斷函數(shù)的方法,也是記錄兩個(gè)下降沿之間的時(shí)間,并將其存入33個(gè)元素的一個(gè)數(shù)組中,數(shù)組的第一個(gè)位置存入的是那個(gè)淫蕩的引導(dǎo)碼,后面的32個(gè)位置存入的是32個(gè)紅外編碼.這個(gè)算法關(guān)鍵的一點(diǎn)就是那個(gè)irisH_bit位變量的作用.那個(gè)位變量是用來記錄邊沿的,無論是下降沿還是上升沿都能記錄,這個(gè)記錄的作用就是只能使相關(guān)的處理只在相應(yīng)的上升沿還是下降沿作用一次.這個(gè)函數(shù)每128us掃描一次.每128us計(jì)數(shù)器irtime增加一次.先來分析程序運(yùn)行時(shí)的情況,當(dāng)沒有下降沿的時(shí)候,一直是高電平一直執(zhí)行if(PB.0==1)下面的語句irtime一直做疊加的操作.當(dāng)加到最大值時(shí)又變?yōu)?做新一輪的疊加操作.這個(gè)是沒有意義的,等到第一個(gè)下降沿到來的時(shí)候進(jìn)入else語句由于是第一個(gè)下降沿那個(gè)這個(gè)irtime就是隨機(jī)的了,這時(shí)ir_en_flag=0,因?yàn)槭浅跏蓟瘯r(shí)的值,下面分兩種情況來說明這時(shí)的情況,如果這個(gè)irtime的時(shí)間剛好在引導(dǎo)碼的區(qū)間,那么就會(huì)清零num,數(shù)組下標(biāo)清0然后進(jìn)入if(ir_en_flag==0)語句將這個(gè)值取入數(shù)組的第一個(gè)位置,然后下一個(gè)下降沿來到了,這時(shí)這個(gè)時(shí)間就是實(shí)實(shí)在在的引導(dǎo)碼的時(shí)間,同樣會(huì)進(jìn)入if(irtime<=110&&irtime>=102)那一個(gè)分支,這時(shí)將數(shù)組下標(biāo)清零,同時(shí)進(jìn)入下一條分支語句if(ir_en_flag==0),這時(shí)將先前存入數(shù)組的每一個(gè)元素覆蓋掉,那個(gè)也就不存在了,而后是32個(gè)紅外數(shù)據(jù)的存入,這里有一個(gè)值得注意的問題在第32個(gè)紅外數(shù)據(jù)接收完成之后,會(huì)有一個(gè)下降沿,這個(gè)是不屬于那32個(gè)數(shù)據(jù)的電平.是多出來的一個(gè)下降沿,當(dāng)這33個(gè)數(shù)據(jù)接收完成的時(shí)候,會(huì)關(guān)斷數(shù)據(jù)的存儲(chǔ),只有下一次再接收到引導(dǎo)碼才會(huì)再次開啟數(shù)據(jù)的存儲(chǔ)功能,這樣做可以有效的把后面的重復(fù)碼干掉,這個(gè)程序的關(guān)鍵仍然是那個(gè)引導(dǎo)碼的時(shí)間只有這個(gè)時(shí)間足夠準(zhǔn)確,足夠狹窄才能和那個(gè)重復(fù)碼區(qū)別開來.
下面提供另一個(gè)過濾重復(fù)碼的方法,直接上源代碼,不解釋.
/*----------------------------------------------------------------------------------------------------
紅外解碼處理函數(shù)
----------------------------------------------------------------------------------------------------*/
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) //引導(dǎo)碼 TC9012的頭碼,9ms+4.5ms
{
ramaddr1= irdata;
num= 0;
}
if(ir_en_flag==1)
{
irtime=0; //如果是重復(fù)碼就將irtime清零,然后退出函數(shù)
return;
}
if(ir_en_flag==0)
{
*ramaddr1= irtime;
ramaddr1++;
irtime= 0;
num++;
if(num==33)
{
irok=1; //32個(gè)數(shù)據(jù)全部存儲(chǔ)完畢,一幀數(shù)據(jù)接收完畢
num=0;
ramaddr1= irdata;
ir_en_flag=1;
}
}
}
}
irtime++;
if(irtiem>=10000) //如果長時(shí)間沒有按下?lián)u控的按鍵,就重新接收下一幀數(shù)據(jù)
{
ir_en_flag=0;
}
}
else
{
return;
}
}
這個(gè)程序去除重復(fù)碼的方法就是老板告訴我的去除重復(fù)碼的方法.這里一幀新的數(shù)據(jù)的接收使能是松開按鍵的時(shí)間超過128ms,算法就是這樣的,不過和上面的那個(gè)程序相比這個(gè)程序沒有上面的那個(gè)好,第一個(gè)是這個(gè)時(shí)間如果設(shè)置的太短的話,過濾的作用,時(shí)間設(shè)置的太短,如果這個(gè)時(shí)間小于兩個(gè)重復(fù)之間的時(shí)間間隔那會(huì)就會(huì)再次使能中斷的接收,從而把原來的數(shù)據(jù)覆蓋掉,導(dǎo)致程序的出錯(cuò).如果這個(gè)時(shí)間設(shè)置的太長,那個(gè)一次按鍵按下去又得等待十年的時(shí)間才能再次開啟紅外的接收,是不是很坑爹。。!,即使這個(gè)時(shí)間設(shè)置的恰到好處,也還是有一個(gè)時(shí)間的延遲的,相比上面的那個(gè)沒有時(shí)間延遲的程序還是有一點(diǎn)瑕疵啊!所以說上面那個(gè)程序,也就是我編的那處程序才是最好的算法和程序.