用的是NEC那个协议。1838的红外接收的数据口接PD6。利用定时器1输入捕获中断方式解码红外遥控。程序里有2个小地方有点看不懂。1、 初始化的时候是 用的是下降沿触发,为什么进入中断要改成上升沿触发了,而且复位还要改成下降沿?
2、 stamp是怎么在TCNT1里计数的,原理有点不懂。
我是新手,可能问的比较菜。大家帮我看看啊。程序如下:
volatile uint16_t stamp=0; //暂存时间印记
volatile uint8_t count=0; //32位数据计数
volatile uint8_t state=0; //状态机
volatile uint8_t data[4]; //保存接收到的遥控数据
#define ir_state_machine_0 0 //无遥控信号
#define ir_state_machine_1 1 //引导码前段
#define ir_state_machine_2 2 //引导码后段
#define ir_state_machine_3 3 //数据码前段
#define ir_state_machine_4 4 //数据码后段
void init_ir(void)
{
//使用8MHz晶振,计数一次为1uS
// CLK/8 对系统时钟8分频并启动计时,下降沿触发中断
TCCR1B |= _BV(CS11);
//TCCR1B &=~( _BV(ICES1)); // 设置为下降沿
TIMSK |= _BV(TICIE1); //允许T/C1输入捕捉中断
state = ir_state_machine_0;
DDRB &=~(_BV(DDB0));
PORTB |=_BV(PORTB0); //启用PB0内部上拉电阻
}
/**************************************
*
* 复位状态设置
*
**************************************/
void reset_ir (void)
{
TCCR1B &=~( _BV(ICES1)); // 设置为下降沿触发
state = ir_state_machine_0; //复位为状态0
count=0;
}
/**************************************
*
* 定时器1输入捕获中断
*
**************************************/
ISR(TIMER1_CAPT_vect)
{
stamp= ICR1; //保存时间印记
TCNT1 = 0; //清零计数器
TCCR1B ^= _BV(ICES1); //切换捕获的触发方式
switch(state)
{
case ir_state_machine_0: //第一次中断,数据丢弃(下降沿中断)
state = ir_state_machine_1;//设置为状态1
break;
case ir_state_machine_1: //接收引导码前半段(9ms)(上升沿中断)
if (stamp >8500&&stamp<9500)
{
state = ir_state_machine_2; //设置为状态2
}
else
{
reset_ir();//干扰信号,复位接收状态
}
break;
case ir_state_machine_2: //接收引导码后半段(4.5ms)(下降沿中断)
if (stamp >4000&&stamp<5000)
{
state = ir_state_machine_3; //设置为状态3
}
else if (stamp >2000&&stamp<2500)//连发码(2.25ms)
{ //可以加一个计数标志对连发计数.
reset_ir();
}
else
{
reset_ir();//干扰信号,复位接收状态
}
break;
case ir_state_machine_3://过滤掉数据码前半部分(560us)(上升沿中断)
state = ir_state_machine_4; //设置为状态4
break;
case ir_state_machine_4://接收数据后半段(0=565us,1=1690us)(下降沿中断)
count++;
if(count<=32)//接收32位数据(低位在前)
{
state = ir_state_machine_3;//回到状态3
data[(count-1)/8]>>=1;//依次将数据存到数组中
if(stamp >1600&&stamp<1800) //保存数据"1"
{
data[(count-1)/8]|=0x80;//
}
}
else
{
reset_ir();//完成接收,复位接收状态
}
break;
}
} |