单片机小白学习之路(三十六)---红外遥控编码

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组(键数据补码)的取反。
上一篇下一篇

猜你喜欢

热点阅读