一、红外接收模块原理
红外接收头内部本身有一个反相,意思就是:平时发送方无信号时接收到的是1,发送方有发送载波时接收头引脚输出的是0,写代码的时候注意这一点。红外协议,你也可以理解成,他对0和1重新做了一些定义:560微秒的高电平加上1.69毫秒定义为逻辑1,560微秒的高电平加上560微秒的低电平定义为逻辑0。需要注意的是这里有一个反相,写代码一定要注意。简单点就是上面说的低电平其实是高电平,高电平其实是低电平。也就是下面的黑色部分其实是低电平,没有黑色的部分是高电平。
二、红外解码实现
首先我们这里的红外解码,针对的是NEC协议进行,其他协议类似处理即可。我们解码只需要根据他发送的时序进行接受就可以了,我们先上程序,然后在对程序里面需要注意的一些问题做进一步解释。我这里红外解码的处理程序全部放到了,中断里面进行处理,由于红外解码时间较长,只要一进入中断至少需要50毫秒,才能出去,如果主程序有一些对刷新率要求很高的事情在里面,使用这个中断函数就会导致,主程序的模块产生一些问题。如果不想出现这个问题,就需要使用定时器延时的方法来进行处理。对于定时器这种方法我们之后在讨论。关于程序里面的一些注意事项,大家看后面的注释就可以啦。
cpp
void ir_int0(void) interrupt 2 //我们这里使用外部中断1
{
uchar i = 0, dat[4] = 0, k = 0, j = 0;
if (IR_PORT == 0) //判断确实是来了红外数据
{
delay8ms(); //将前面9毫秒的低电平先过去一段时间
if (IR_PORT == 0) //在进行确认确实是来了红外起始信号
{
delay4ms(); //将4.5毫秒的高电平过去一段时间
if (IR_PORT == 1)//在进行判断确实是其实信号里面高电平那一段来了
{
while (IR_PORT == 1); //使用while循环将其实信号里面剩余的高电平给消耗掉
for (j=0; j<4; j++) //由于总共有4个字节的数据
{
for (i=0; i<8; i++) //每个字节有8位,从LSB->MSB依次接收
{
k = 0; //每次开始必须将k清零,k保存的是上一次传输的数据
while (IR_PORT == 0); //使用while循环将0或1开始的560微秒给消耗掉
//由于0和1剩余的高电平信号的长短不一致,我们并不能知道来的是0还是1
//因此我们首先需要记录来的高电平持续的时间长短
//然后根据时间长短在进行判断是0还是1
while (IR_PORT == 1) //使用while将来的高电平消耗一下
{
delay10us(); //这里的每隔10微秒做一次计数
k++; //根据k的大小我们就可以判断是0还是1
}
if (k <= 60) //由于逻辑0的高电平只有560微妙,因此只要少于60的传过来就是0
{
k = 0;
}
else //否则传输过来的就是1
{
k = 1;
}
dat[j] = ((dat[j] >> 1) | (k << 7)); //将接收到的数据保存在数组里面
}
}
if ((dat[0] == 0x00) && (dat[1] == 0xff)) //对数据做进一步的校验
{
uart_send_byte(dat[2]); //将正确的键值通过串口进行打印
uart_send_byte(dat[3]);
}
}
}
}
}