AVR单片机使用外部中断和定时器的NEC红外解码程序

2019-04-15 17:05发布

    刚开始学习AVR单片机,移植了一个以前51上红外解码的程序,使用外部中断0和定时器0,使用外部8M晶振。 有一点可能需要大家注意一下,就是解码的时候定时器的配置。因为AVR单片机定时器0是一个8bit的定时器,根据个人晶振大小,大家要选择一个合适的定时器时钟的分频,既要满足NEC时序的时间长度要求,又要注意其分辨率是不是足够。 在使用时,首先运行初始化函数,程序里定义了一个接收成功的标志位全局变量,用户操作后要置0; Ir_buf[ ]是接收到的数据的解码。 下面是程序: /**************************************************************************** * NEC 红外遥控接收 * 文件名:IR_Receive.c * 资源占用:定时器0; 外部中断1 * AVR8515 晶振:8MHz * * 作者:DuPeng * 版本日期:2016-11-1 18:20:32 *****************************************************************************/ #include "iom8515.h" #include "IR_Receive.h" #include "ModeManager.h" #define DQ_IR (0x01<<2) //PD2 #define DQ_status() (PIND & DQ_IR) //Read PD2 unsigned char IR_success = 0; //遥控接收成功 unsigned char Ir_Buf[4]; //用于保存解码结果 /**************************************************************************** * 红外接收初始化 ****************************************************************************/ void NEC_IR_init(void) { DDRD=0xFB; //PD2 INT0 INPUT SREG = 0x80; //使能全局中断 MCUCR=0x02; // 下降沿有效 GICR=0x40; //使能外部中断0 } /************************************* * 获取低电平时间 **************************************/ unsigned int Ir_Get_Low() { TCCR0 = 0x05; //开启定时器0 1024分频 TCNT0 = 0x00; //初始值 while (!DQ_status()); //等待高电平 TCCR0 = 0x00; return TCNT0; } /************************************** * 获取高电平时间 ***************************************/ unsigned int Ir_Get_High() { TCCR0 = 0x05; //开启定时器0 1024分频 TCNT0 = 0x00; //初始值 while (DQ_status()); //等待低电平 TCCR0 = 0x00; return TCNT0; } /**************************************************************************** * 外部中断服务函数 ****************************************************************************/ #pragma vector=INT0_vect __interrupt void int1_isr() { unsigned int temp; char i,j; temp = Ir_Get_Low(); if ((temp < 66) || (temp > 74)) //引导脉冲低电平8500~9500us { return; } temp = Ir_Get_High(); if ((temp < 31) || (temp > 39)) //引导脉冲高电平4000~5000us { return; } for (i=0; i<4; i++) //4个字节 { for (j=0; j<8; j++) //每个字节8位 { temp = Ir_Get_Low(); if ((temp < 1) || (temp > 7)) //200~800us { return; } temp = Ir_Get_High(); if ((temp < 1) || (temp > 16)) //200~2000us { return; } Ir_Buf[i] >>= 1; if (temp > 8) //1120us Ir_Buf[i] |= 0x80; } } IR_success = 1; // 遥控接收成功 } .h文件: /**************************************************************************** * NEC 红外遥控接收 ( 头文件 ) * 作者:DuPeng * 版本日期:2016-11-1 18:20:32 *****************************************************************************/ #ifndef _IR_Receive_H #define _IR_Receive_H #define key_power 0x45 #define key_menu 0x47 #define key_test 0x44 #define key_back 0x43 #define key_play 0x15 #define key_del 0x0D // EQ #define key_last 0x07 #define key_next 0x09 #define key_add 0x40 // + #define key_minus 0x19 // - #define key_0 0x16 #define key_1 0x0c #define key_2 0x18 #define key_3 0x5E #define key_4 0x08 #define key_5 0x1C #define key_6 0x5A #define key_7 0x42 #define key_8 0x52 #define key_9 0x4A extern unsigned char Ir_Buf[4]; //用于保存解码结果 extern unsigned char IR_success; // 遥控接收成功 void NEC_IR_init(void); // 红外接收初始化 #endif