• 【单片机】18-红外线遥控


    一、红外遥控背景知识

    1.人机界面

    (1)当面操作:按键,旋转/触摸按键,触摸屏

    (2)遥控操作:红外遥控,433M/2.4G无线通信【穿墙能力强】,蓝牙-WIFI-Zigbee-LoRa等无线网络

    2.红外遥控相关知识

    1.红外线基本知识

    红外线和紫外线人眼看不到,人可以看到的红外线是其中的一部分

    红外线传播不远

    2.红外发射和接收

    单向通信

    一个发送器【供电发光,发送红外信号】对应一个接收器【光电传感器】

    光【1】----》电【0】

    没有反应的可能性:

    1)发送和接收的频率不同

    2)上层协议不同

    万能遥控器:是包含多种协议

    3.38KHz载波和数字信号,调制

    载波:无线通信过程中,1和0无法在空气中传播,将1和0叠加在载波上

    数字信号:1和0

    调制:将1和0叠加在载波上

    解调:将调制的数据反调制,将数据取出来

    电话线上的猫:先将网络型号转换为电话线可以传播的信号然后进行传播

    4.红外遥控器通信协议

    遥控器和接收端的交互

    二、原理图分析

    1.原理图和接线

    1.接收端原理图

    2.IR1接收模块原理

    发送(调制)和接收(解调)

    (1)一体集成式接收头内部已经内置了红外载波解调功能,从IRD引脚出来的就是通信的二进制信号。所以单片机的IO可以直接接IRD引脚来读取红外信号中的通信信息。所以38KHz的载波的调制和解调过程对编程是透明的(可以忽视的)

    (2)红外接收头内部本身是有个相反的,意思是:平时发送方无发送信号时接收到的是1,有发送载波时接受头IRD引脚输出的是0,意味着后面时序图是相反的。

    2.红外遥控器全解析

    https://www.cnblogs.com/zhugeanran/p/9334289.html

    1.功能演示

    2.拆解

    3.芯片bingding工艺

    3.红外遥控系统工作过程综述

    1.发射端

    一般是一个红外遥控器,内置一个芯片,检查按键,收集键值,调制到38kHz

    2.传播

    通过红外头传播

    3.接收端

    对载波进行解调,得到1和0的信号,解开键值

    三、NEC协议讲解

    红外协议之NEC协议_Linux教程_Linux公社-Linux系统门户网站

    https://www.cnblogs.com/mylinux/p/5084264.html

    第 16 章 红外通信实验

    1.红外遥控协议原理

    因为逻辑1和逻辑0在空气中传输过程中是不稳定的

    1.红外遥控协议的作用

    从二进制的层面上定义了如何传输一帧数据(传输逻辑1应该多长的时间周期,传输逻辑0应该多长时间周期)

    数据是一帧一帧的传,不可以出现一帧没有传输完就传输下一帧。

    2.红外遥控的特征

    • 8 位地址和 8 位命令长度
    • 为提高可靠性每次传输两遍地址(用户码)和命令(按键值)
    • 通过脉冲串之间的时间间隔来实现信号的调制
    • 38Khz 载波
    • 每位的周期为 1.12ms(逻辑0) 或者 2.25ms(逻辑1)

    3.解析协议的关键点

    时间周期【传输逻辑1和传输逻辑0的时间不同】

    4.不同协议的差异

     时序的不同,调制的方式不同,但是低层还是按照38KHz发送

    5.为什么需要协议?

    只需要低层协议就足够

    2.NEC协议的关键点

    1.载波和信号

    2.关键:1和0分别如何表示

    3.数据是一帧一帧的帧传输

    接收方无法预测什么时候可以接收完毕【异步:轮询或者中断】

    4.NEC是串行协议

    数据是一个bit一个bit的传输

    5.时序中的时间仍然是关键点

    四、官方示例代码

    1.如何得到一段代码精确延时时间【软仿真】

    涉及到延时时间问题时,一定要先确定频率

    延时等级问题

    注意点:每一次修改完后要记得重新运行一次

    实际上耗费时间包括:

    1)调用函数的时间

    2)函数内部代码的执行

    1. #include
    2. #include"ired.h"
    3. void DelayMs(unsigned int x) //0.14ms误差 0us
    4. {
    5. unsigned char i;
    6. while(x--)
    7. {
    8. for (i = 0; i<13; i++)
    9. {}
    10. }
    11. }
    12. void func(void){
    13. unsigned char a=1;
    14. }
    15. void main(){
    16. unsigned char a=0,y=0;
    17. a=1; //392us
    18. DelayMs(1); // 529us 实际上使用529-392=137us
    19. DelayMs(70); //8945 实际上使用8945-529=8416us
    20. func();
    21. y=a+4;
    22. a=2;

    2.中断函数

    1. void ReadIr() interrupt 0
    2. {
    3. unsigned char j,k;
    4. unsigned int err;
    5. Time = 0;
    6. DelayMs(70); // 8416us---软仿真测试
    7. //时序图中要持续9us的时间处于低电平(相反)
    8. if (IRIN == 0) //确认是否真的接收到正确的信号
    9. {
    10. //检查是否超时
    11. err = 1000; //1000*10us=10ms,超过说明接收到错误的信号
    12. /*当两个条件都为真时循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
    13. 侯,程序死在这里*/
    14. //每过136ms去检查是否变为高电平
    15. //IRIN==0:表示此时还是低电平,此时9ms还没有到
    16. //err>0:避免死循环【超时设置】
    17. while ((IRIN==0) && (err>0)) //等待前面9ms的低电平过去
    18. {
    19. DelayMs(1); // 136us【在8.4us后不断检查】
    20. err--;
    21. }
    22. //超过9us,进入4.5ms
    23. if (IRIN == 1) //如果正确等到9ms低电平
    24. {
    25. err = 500;//超时检查
    26. while ((IRIN==1) && (err>0)) //等待4.5ms的起始高电平过去
    27. {
    28. DelayMs(1);
    29. err--;
    30. }
    31. //开始传输数据
    32. for (k=0; k<4; k++) //共有4组数据
    33. {
    34. for (j=0; j<8; j++) //接收一组数据【从低位开始读】
    35. {
    36. err = 60;
    37. //这里是为了消耗每接受一个数据前面的560us的时间
    38. while ((IRIN==0) && (err>0))//等待信号前面的560us低电平过去
    39. {
    40. DelayMs(1);//延时1表示延时136us【软仿真】
    41. err--;
    42. }
    43. err = 500;
    44. //开始区分逻辑1(1.69ms)和逻辑0(0.56ms)
    45. while ((IRIN==1) && (err>0)) //计算高电平的时间长度。
    46. {
    47. DelayMs(1);//0.14ms
    48. //逻辑1(1.69ms)和逻辑0(0.56ms)
    49. //1690/136=12个
    50. //560/136=4个
    51. //如果time》12则表示为逻辑1,如果time《4则表示为逻辑0
    52. Time++;//计算,看有多少个136us
    53. err--;
    54. if (Time > 30)//136*30=4080us【超时机制】
    55. //
    56. {
    57. EX0 = 1;
    58. return;
    59. }
    60. }
    61. //循环结束后,判断此时time的大小,如果
    62. IrValue[k] >>= 1; //k表示第几组数据
    63. if (Time >= 8) //如果高电平出现大于565us,那么是1
    64. {
    65. IrValue[k] |= 0x80;//将得到的数据放在高位
    66. }
    67. Time = 0; //用完时间要重新赋值
    68. }
    69. }
    70. }
    71. if (IrValue[2] == ~IrValue[3])//判断两个命令(键值)是否相同---》检验
    72. {
    73. return;
    74. }
    75. }
    76. }

    3.初始化函数

    1. void IrInit(void)
    2. {
    3. IT0=1;//外部中断0中断源类型选择位:下降沿触发
    4. EX0=1;//外部中断0中断允许位
    5. EA=1; //打开总中断
    6. IRIN=1;//初始化端口,平时电平为高电平【因为材料问题规定的】,所以才初始化为高电平
    7. }

    五、代码的移植

    1.全局变量的定义

    全局变量在哪个C文件中用就在哪个C文件中定义
    不能放在头文件中定义
     如果在多个C文件中都要用到同一个全局变量,应该在一个主要的C文件中定义
    然后其他C文件中extern声明即可

    ired.c

    1. // 全局变量在哪个C文件中用就在哪个C文件中定义
    2. // 不能放在头文件中定义
    3. // 如果在多个C文件中都要用到同一个全局变量,应该在一个主要的C文件中定义
    4. // 然后其他C文件中extern声明即可
    5. sbit IRIN = P3^2;
    6. unsigned char IrValue[5]; // IrValue的0-3用来放原始数据,4用来放经过校验确认无误的键值
    7. unsigned char Time;

    main.c

    extern unsigned char IrValue[6];//声明

    2.红外遥控器上的键值

    1.测试

    2.结果

    3.延时时间配合

    结合上面的“如何得到一段代码精确延时时间【软仿真】”去验证一个延迟时间函数对应多长时间,然后要求这个地方不超过9ms即可。

    4.屏蔽无效数据

    将经过校验确认无误的键值输出

    5.程序改良

    原来我们将主程序写在中断中,实际上不能写在里面。

    所以我们可以通过定时器来处理延时,因为在定时器在运行时,CPU还可以工作。

  • 相关阅读:
    DSA之查找(2):树表的查找
    【电商】电商后台系统整体介绍
    第10章 RDB持久化
    中国MEMS陀螺仪应用及市场需求空间测算研究报告
    ES6 Promise详解
    Qt事件处理机制(二)重写事件处理函数:重写鼠标移动事件,实现用鼠标拖动按钮在widget中自由移动!
    Springboot毕业设计毕设作品,婚纱租赁系统设计与实现
    深度学习_3_张量运算
    RocketMQ的Schedule example
    HTML期末学生大作业:中华传统文化【苏绣手工艺】带psd设计图(15页)
  • 原文地址:https://blog.csdn.net/m0_63077733/article/details/133713652