刚开始学习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