|
最近參考了網(wǎng)上的51紅外線遙控遙控信號(hào)解碼程序,編寫了基于attiny13的NEC紅外線遙控信號(hào)解碼程序,拿出來給大家共勉,歡迎大家批評指正。程序如下:
#include <avr/io.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define star() TCCR0B=(1<<CS01)|(1<<CS00) //啟動(dòng)定時(shí)器,64分頻,定時(shí)器時(shí)鐘周期在53.3us~58.2us之間,中位數(shù)55.75us
#define stop() TCCR0B=0 //停止定時(shí)器
#define ir_in PB1 //int0引腳定義
volatile uchar ir_flag=0;
volatile uchar ir_da[4];
/****************************************************/
uchar getHtime(void)
{
TCNT0=0;
star(); //開始計(jì)時(shí)
while (PINB&(1<<ir_in)) //等待高電平結(jié)束
{
if (TCNT0>250) break; //高電平時(shí)間太長不合法,退出等待
}
stop(); //停止計(jì)時(shí)
return TCNT0;
}
/****************************************************/
uchar getLtime(void)
{
TCNT0=0;
star(); //開始計(jì)時(shí)
while ((PINB&(1<<ir_in))==0) //等待低電平結(jié)束
{
if (TCNT0>250) break; //高電平時(shí)間太長不合法,退出等待
}
stop(); //停止計(jì)時(shí)
return TCNT0;
}
/****************************************************/
ISR(INT0_vect) //外部中斷
{
static uchar step=1; //用于區(qū)分按鍵碼和連續(xù)碼以執(zhí)行不同的中斷程序
uchar i,j;
uchar byt=0;
uchar time;
if (step) //剛按下遙控器的按鍵,執(zhí)行下面的程序段
{
time=getLtime(); //接收并判定引導(dǎo)碼的 9ms 低電平,
if((time<152)||(time>171)) //時(shí)間判定范圍為 8.5~9.5ms,超過此范圍則說明為誤碼,直接退出
{
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
return; //結(jié)束外部中斷程序
}
time=getHtime(); //接收并判定引導(dǎo)碼的 4.5ms 高電平
if ((time<71)||(time>89)) //時(shí)間判定范圍為 4.0~5.0ms,超過此范圍則說明為誤碼,直接退出
{
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
return; //結(jié)束外部中斷程序
}
for (i=0; i<4; i++) //循環(huán)接收 4 個(gè)字節(jié)
{
for (j=0; j<8; j++)
{
time=getLtime();
if ((time<6)||(time>14)) //時(shí)間判定范圍為 340~780us,超過此范圍則說明為誤碼,直接退出
{
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
return; //結(jié)束外部中斷程序
}
time=getHtime();
if ((time>5)&&(time<15)) byt>>=1; //時(shí)間判定范圍為 340~780us,在此范圍內(nèi)說明該 bit 值為 0
else if ((time>25)&&(time<35)) //時(shí)間判定范圍為 1460~1900us,在此范圍內(nèi)說明該 bit 值為 1
{
byt>>=1;
byt|=0x80;
}
else
{
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
return; //結(jié)束外部中斷程序
}
}
ir_da[i]=byt;
}
ir_flag=1;
step=0; //如果按鍵未松開,下次中斷執(zhí)行連發(fā)碼處理程序
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
}
else //如果是連發(fā)碼執(zhí)行下面的程序段
{
time=getLtime(); //接收并判定連發(fā)碼引導(dǎo)碼的 9ms 低電平
if((time<152)||(time>171)) //時(shí)間判定范圍為 8.5~9.5ms,超過此范圍則說明為誤碼,直接退出
{
step=1; //下次中斷執(zhí)行按鍵處理程序
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
return; //結(jié)束外部中斷程序
}
time=getHtime(); //接收并判定連發(fā)引導(dǎo)碼的 2.25ms 高電平
if ((time<36)||(time>44)) //時(shí)間判定范圍為 2.0~2.5ms,超過此范圍則說明為誤碼,直接退出
{
step=1; //下次中斷執(zhí)行按鍵處理程序
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
return; //結(jié)束外部中斷程序
}else //確定為連發(fā)碼
{
ir_flag=1;
step=0; //如果按鍵仍未松開,下次中斷繼續(xù)執(zhí)行連發(fā)碼處理程序
GIFR=(1<<INTF0); //寫入 ”1” 來清零外部中斷標(biāo)志
}
}
}
/****************************************************/
int main(void)
{
PORTB=0xff;
MCUCR=(1<<ISC01); //INT0 的下降沿產(chǎn)生異步中斷請求
GIMSK=(1<<INT0); //外部引腳中斷使能
sei(); //開全局中斷
while (1)
{;}
}
attiny13使用內(nèi)部時(shí)鐘,電源電壓5V時(shí)實(shí)測1.15MHz左右。編譯器為GCC
|
評分
-
查看全部評分
|