https://static.assets-stash.eet-china.com/album/old-resources/2010/6/24/c99b0a49-3a8e-4a3e-b989-4575f90d87e6.rar" target=_blank>
MCU ATmega16 作者 1121
编译器 ICCAVR 晶振 16M
时间 2010.6.24
注意红外传送的数据中,(A)0 是用0.56ms的低电平和0.565ms的高电平表示,1 是用0.56ms的低电平和1.69ms的高电平表示,而不是反过来,所以用高电平的持续时间来判断是0还是1,网上很多资料都是说(B)“0 是用0.56ms的高电平和0.565ms的低电平表示 1 是用0.56ms的高电平和1.69ms的低电平表示”,但我试了很多次都不行,后来反过来就可以啦。原来A说法是发射端的时序,B种时序是接收端的时序,两种是反过来的。
当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,
这108ms发射代码由一个低电平引导码(9ms),一个高电平结果码(4.5ms),
低8位地址码(9ms~18ms),高8位地址码(9ms~18ms),8位数据码(9ms~18ms)
和这8位数据的反码(9ms~18ms)组成。如果键按下超过108ms仍未松开,接下
来发射的代码(连发码)将仅由起始码(9ms)和结束码(2.25ms)组成。
/***************************************************************/
外中断0服务程序 用来接收到红外发送的数据
/***************************************************************/
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
uchar i,j,k = 0;
flag="1";
GICR = 0x00; //禁止外部中断 关闭外部中断,开始接受数据
addr[0]=0;
addr[1]=0;
addr[2]=0;
addr[3]=0; //全部数据清零
for(i = 0;i < 18;i++) //低电平引导码9ms
{
delay_nus(480);
if(PIND & (1 << PD2)) //9MS内有高电平,则判断为干扰,退出处理程序
{
GICR |= (1 << INT0); //使能外部中断4
return; //返回主函数
}
}
while(!(PIND & (1 << PD2))); //等待9ms低电平过去
while(PIND & (1 << PD2)); //等待4.5ms高电平过去
for(i = 0;i < 4;i++) //32位二进制码
{
for(j = 0;j < 8;j++) //8位二进制码
{
while(!(PIND & (1 << PD2))); //等待变高电平,因为主要是判断高电平的长度
while(PIND & (1 << PD2)) //计算高电平时间
{
delay_nus(100); //0.1ms
k++; //计算有多少个0.1ms
if(k >= 30) //高电平时间过长,则退出处理程序
{
GICR |= (1 << INT0); //使能外部中断
return; //返回主函数
}
}
addr = addr >> 1; //接受一位数据
if(k >= 8)
{
addr = addr | 0x80; //高电平时间大于0.56,则为数据1,一般取0.8ms
}
k = 0; //计时清零
}
}
if((addr[1]!=0xff) && (addr[2]!=(~addr[3])))//数据验证,判断addr[2]是不是addr[3]的反码
{
GICR |= (1 << INT0); //使能外部中断
return; //返回主函数
}
send_char(addr[0]); //把接收到的数据通过串口发送到电脑
delay_nms(5); //延时一下,可以减少误码率
send_char(addr[1]);
delay_nms(5);
send_char(addr[2]);
delay_nms(5);
send_char(addr[3]);
delay_nms(5);
GICR |= (1 << INT0); //使能外部中断
}
https://static.assets-stash.eet-china.com/album/old-resources/2010/6/24/c99b0a49-3a8e-4a3e-b989-4575f90d87e6.rar
文章评论(0条评论)
登录后参与讨论