单片机小白学习之路(三十六)---红外遥控编码
2018-10-14 本文已影响0人
飞向深空
目标:红外遥控编程
、鉴别引导码、数据码和连发代码
引导码为1个下降沿(负跳变)后13.5ms跟着第1位数据码下降沿;
数据码根据发送的0和1不同,在1个下降沿之后1.125ms(数据0)或2.25ms(数据1)后是下1位数据下降沿;
连发代码是在1个结束码下降沿后108ms之后产生;
所有的判断都是基于下降沿(触发外部中断)开始到下一个下降沿之间的时间长短,这个时间是判断所有传输数据类型的唯一条件。
2、数据位的读取:设定变量a和b,分别在计时器中断和外部中断中进行累加,在每1个下降沿触发外部中断都重置计时器累加变量(a=0),同时在计时器中断中判断a累加计时是否超过1.125ms,而小于2.25ms,如果有则对应序号为b的数据位=1;
3、判断计时器中断中累加计时a,计时时间超过15ms(引导码时长13.5ms)表示错误或数据以及传输完,重置a和b;
作者:zhb2004xp
来源:CSDN
原文:https://blog.csdn.net/zhb2004xp/article/details/80951011?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!
#include <reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA = P3^0;
sbit LSB = P3^1;
sbit LSC = P3^3; //数码管位选
sbit IRIN = P3^2; //数据输入/输出端口
u8 IrValue[6];
u8 Time; //用于计数的间接数值
u8 DisplayData[8];
u8 code ShuzList[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0X76};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、H的显示码
void delay(u16 i) //延时函数,输入1相当于延时10us
{
while(i--);
}
void DigDisplay() //数码管显示函数
{
u8 i;
for(i=0;i<3;i++){
switch(i){
case(0): LSA = 0;LSB = 0;LSC = 0;break;
case(1): LSA = 1;LSB = 0;LSC = 0;break;
case(2): LSA = 0;LSB = 1;LSC = 0;break;
}
P0 = DisplayData[i]; //发送数据
delay(100);//间隔一段时间扫描
P0 = 0x00; //消隐
}
}
void IrInit() //初始化红外线接收
{
IT0 = 1; //设置为下降沿触发
EX0 = 1; //打开外部中断0允许位
EA = 1; //开启总中断
IRIN = 1; //初始化端口,这步可以省略
}
void main()
{
IrInit();
while(1){
DisplayData[0] = ShuzList[IrValue[2]/16]; //数据的高位
DisplayData[1] = ShuzList[IrValue[2]%16]; //数据的低位
DisplayData[2] = smgduan[16];
DigDisplay();
}
}
void ReadIr() interrupt 0
{
u8 j,k;
u16 err; //一个用于延时的间接数
Time = 0;
delay(700); //先延时7ms
if(IRIN==0){
err = 1000; // 1000*10us= 10ms
while((IRIN==0)&&(err>0)){ //只要这两个条件任意一个不满足就跳出循环
delay(1); //err是1000,进入1000此后此时又延时10ms,大于引导码低电平时间,说明传输失败
err--;
}
if(IRIN==1){
err=500; //500*10us= 5ms
while((IRIN==1)&&(err>0)) //延时大约5ms
{
delay(1);
err--;
} //**此行上面是引导波形的设置**
for(k=0;k<4;k++){ //4个字节
for(j=0;j<8;j++){ //每个字节8位
err = 60;
while((IRIN==0)&&(err>0)){ //低电平延时约560us
delay(1);
err--;
}
err=500; //500*100us= 50ms, 这里是随便弄得,计时判断关键是Time
while((IRIN==1)&&(err>0)){ //计算高电平的时间长度
delay(10); //延时100us
err--;
Time++;
if(Time>30){
return; //此时已经远远超过了判断时间,错误
}
}
IrValue[k]>>=1; //数据移位,由于数据是低位先传输所以是右移,k表示第几组数据
if(Time>8){ //如果高电平出现大于565us,那么是1
IrValue[k] |= 0x80;
}
Time = 0; //用完时间要重新赋值
}
}
if(IrValue[2] != ~IrValue[3]){ //第2组数据(键数据码)不等于第3组(键数据补码)的取反那么信息错误
return;
}
}
}
}
步骤梳理:
- 先延迟约7ms,判断输入(IRIN)是高低电平,如果此时还是低的话则延时判断如果超过10ms大于引导码的低电平时间则传输失败。发先 是高电平了再延时大约5ms。这是引导码的部分
- 因为是4个字节,每个字节又是8位,所以用一个嵌套循环,for4里面嵌套for8,先延时个560us(560us是关键点,因为0和1的低电平都是560us,判断位是0,1的关键就是后面高电平的长度),这里需要借助一个中间量Time来判断高电平的长度,也就是Time每加1就相当于延时了100us。后面先进行移位,再判断Time大小,Time大于8相当于高电平已经持续了0.8ms,超过了数据0的高电平时间所以判断传输的是1。如果是0就不用往里面写了因为初始8位都是0.
- 最后在嵌套循环外面判断一下第2组数据(键数据码)等不等于第3组(键数据补码)的取反。