最近参考了网上的51红外线遥控遥控信号解码程序,编写了基于attiny13的NEC红外线遥控信号解码程序,拿出来给大家共勉,欢迎大家批评指正。程序如下:
#include <avr/io.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define star() TCCR0B=(1<<CS01)|(1<<CS00) //启动定时器,64分频,定时器时钟周期在53.3us~58.2us之间,中位数55.75us
#define stop() TCCR0B=0 //停止定时器
#define ir_in PB1 //int0引脚定义
volatile uchar ir_flag=0;
volatile uchar ir_da[4];
/****************************************************/
uchar getHtime(void)
{
TCNT0=0;
star(); //开始计时
while (PINB&(1<<ir_in)) //等待高电平结束
{
if (TCNT0>250) break; //高电平时间太长不合法,退出等待
}
stop(); //停止计时
return TCNT0;
}
/****************************************************/
uchar getLtime(void)
{
TCNT0=0;
star(); //开始计时
while ((PINB&(1<<ir_in))==0) //等待低电平结束
{
if (TCNT0>250) break; //高电平时间太长不合法,退出等待
}
stop(); //停止计时
return TCNT0;
}
/****************************************************/
ISR(INT0_vect) //外部中断
{
static uchar step=1; //用于区分按键码和连续码以执行不同的中断程序
uchar i,j;
uchar byt=0;
uchar time;
if (step) //刚按下遥控器的按键,执行下面的程序段
{
time=getLtime(); //接收并判定引导码的 9ms 低电平,
if((time<152)||(time>171)) //时间判定范围为 8.5~9.5ms,超过此范围则说明为误码,直接退出
{
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
return; //结束外部中断程序
}
time=getHtime(); //接收并判定引导码的 4.5ms 高电平
if ((time<71)||(time>89)) //时间判定范围为 4.0~5.0ms,超过此范围则说明为误码,直接退出
{
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
return; //结束外部中断程序
}
for (i=0; i<4; i++) //循环接收 4 个字节
{
for (j=0; j<8; j++)
{
time=getLtime();
if ((time<6)||(time>14)) //时间判定范围为 340~780us,超过此范围则说明为误码,直接退出
{
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
return; //结束外部中断程序
}
time=getHtime();
if ((time>5)&&(time<15)) byt>>=1; //时间判定范围为 340~780us,在此范围内说明该 bit 值为 0
else if ((time>25)&&(time<35)) //时间判定范围为 1460~1900us,在此范围内说明该 bit 值为 1
{
byt>>=1;
byt|=0x80;
}
else
{
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
return; //结束外部中断程序
}
}
ir_da[i]=byt;
}
ir_flag=1;
step=0; //如果按键未松开,下次中断执行连发码处理程序
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
}
else //如果是连发码执行下面的程序段
{
time=getLtime(); //接收并判定连发码引导码的 9ms 低电平
if((time<152)||(time>171)) //时间判定范围为 8.5~9.5ms,超过此范围则说明为误码,直接退出
{
step=1; //下次中断执行按键处理程序
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
return; //结束外部中断程序
}
time=getHtime(); //接收并判定连发引导码的 2.25ms 高电平
if ((time<36)||(time>44)) //时间判定范围为 2.0~2.5ms,超过此范围则说明为误码,直接退出
{
step=1; //下次中断执行按键处理程序
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
return; //结束外部中断程序
}else //确定为连发码
{
ir_flag=1;
step=0; //如果按键仍未松开,下次中断继续执行连发码处理程序
GIFR=(1<<INTF0); //写入 ”1” 来清零外部中断标志
}
}
}
/****************************************************/
int main(void)
{
PORTB=0xff;
MCUCR=(1<<ISC01); //INT0 的下降沿产生异步中断请求
GIMSK=(1<<INT0); //外部引脚中断使能
sei(); //开全局中断
while (1)
{;}
}
attiny13使用内部时钟,电源电压5V时实测1.15MHz左右。编译器为GCC
|