|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2008-4-7 23:23:48
|
显示全部楼层
////函数功能:红外接收
////硬件连接:红外接收的IRDAT与INT1连,PC口语LED连接,PA2与喇叭链接,(k20按键)也与INT1连
////实验现象:开始灯全亮,如果能进入红外接收中断喇叭响,根据按键的不同用LED显示键码。如按K20能进入中断证明红外接收有问题
////内部时钟:4MHZ
////头文件
#include <avr/interrupt.h>
#include <avr/io.h>
static unsigned char state=0,first_in=1,stemp=0,bit=0,byte=0,press_key_0k,buf[4];
static unsigned int time1,time2;
//****************************红外接收中断服务函数********************************
SIGNAL (INT1_vect) //当INT出现下降沿跳变是,进入中断
{
cli();
switch (state)
{
case 0: //引导码判断 9MS=36000个计数周期
if (first_in==1) //当第一次进入中断时
{
TCCR1A&=0XFC; //T/C1普通模式,无分频
TCCR1B&=0XE1;
TCCR1B|=0X01;
time1=TCNT1;
first_in=2;
}
else //第二次进入中断
{
time2=TCNT1;
if ( ((time2-time1)<30000) | ((65535-time1+time2)<30000) ) //抗干扰
{
state=0;
}
else
{
state=1;
}
first_in=1;
}
break;
case 1: //time2-time=4.5ms间隔时间等待后,之后读数据,到case2
time1=TCNT1; //但time2-time1=2.25ms,为按键还没放开,不读数据,到case0
if ( ((time1-time2)<13500) | ((65535-time2+time1)<13500) ) //取3.375MS做判断,为13500个计数周期
{
state=2;
press_key_0k=0;
}
else
{
state=2;
press_key_0k=1;
}
break;
case 2: //0.56ms低电平等待后
if (press_key_0k) state=0;
else
{
time1=TCNT1;
state=3;
}
break;
case 3: //0或1的判断
time2=TCNT1;
if ( ((time2-time1)>4480) | ((65535-time1+time2)>4480) ) //时间较长者为1
{
stemp|=(1<<bit);
bit++;
}
else
{
stemp&=(~(1<<bit));
bit++;
}
if (bit==8)
{
bit=0;
buf[byte]=stemp;
byte++;
}
if (byte>=4)
{
if ((buf[2]&buf[3])==0X00) && ((buf[2]|buf[3])==0xff) ) //原码反码判断数据是否有错
{
DDRA|=0X04;
PORTA&=0XFB; //喇叭响,表示程序能运行到这里(在测试时用,测试完删除)
PORTC=buf[2];
}
else
{
PORTC=0XF0; //用于检测错误码,测试完删除
}
byte=0;
state=0;
}
else
{
state=2;
}
break;
}
sei();
}
//*****************************主函数*********************************************
int main (void)
{
///////////端口初始化
DDRC=0XFF; //PC口为LED输出
PORTD|=0X08; //PD3是能内部上拉
DDRD&=0XF7; //PD3(int1)接红外输入
///////////外部中断1初始化
MCUCR&=0XF7; //电平变化沿触发
MCUCR|=0X04;
GICR|=0X80; //中断是能
GIFR&=0X80;
sei(); //开中断,允许接收红外信号
while (1)
;
} |
|