写点什么

STM32 入门开发 制作红外线遥控器 (智能居家 - 万能遥控器)

作者:DS小龙哥
  • 2022 年 8 月 16 日
    重庆
  • 本文字数:3777 字

    阅读完需:约 12 分钟

一、环境介绍

MCU: STM32F103ZET6


编程软件环境: keil5


红外线传输协议: NEC 协议---38KHZ 载波:。NEC 协议是红外遥控协议中常见的一种。


编码发送思路: 延时函数模拟 38KHZ + PWM 产生 38KHZ 两种方式


代码风格: 模块化编程,寄存器直接操作方式

二、NEC 协议与相关硬件介绍

2.1 NEC 协议介绍

红外线协议有很多,本章节主要是针对 NEC 协议讲解,只要把 NEC 协议原理搞懂了,其他协议都是一样的使用;如果想要模拟空调遥控器,去控制美的空调、格力空调这些设备,就需要按照美的、格力空调的协议发送;如果不知道协议长什么样,可以将逻辑分析仪插在红外线接收头的引脚上,拿个正常的空调遥控器对着接收头按一下,然后采集数据分析,即可得到协议规律,然后网络上也有空调按键值功能的说明文档,调试一下即可。

2. 2 使用的相关硬件

因为要模拟红外线遥控器,就需要一个红外线发射管;在学习阶段,如果不想自己搭建电路,可以买现成的模块。 买模块连接也是比较稳定,接线也比较简单,VCC 和 GND 接好之后,把 DAT 引脚接到 STM32 任意一个 IO 口上即可,如果想用硬件 PWM 控制发送,那么引脚接到 STM32 的 PWM 输出脚即可。


2.3 完成 NEC 协议编码发送

先看一段红外线接收头引脚上采集的 NEC 协议的电平: 这是接收端采集的。



红外线接收头的硬件特性: (注意: 这里是针对 NEC 遥控器协议来说明),下图就是当前使用的红外线接收头。



收到 38KHZ 的红外光,IN 引脚就输出低电平;没有收到 IN 引脚就输出高电平。


NEC 红外线协议说明:(这是站在接收端解码的角度分析的)


一段独立的 NEC 协议数据包由引导码+32 位数据组成。


引导码: 9ms 的高电平 + 4.5ms 低电平组成。


32 位数据就是: 8 位用户码+ 8 位用户反码+ 8 位按键码+8 位按键反码


每个数据位之间的间隔时间是 0.56ms(低电平)


NEC 协议是依靠收到的高电平持续时间来判断数据 0 和数据 1;高电平持续时间是 0.56ms 表示数据 0,高电平持续时间是 1.68ms 表示数据 1。


只要明白上面说的两个特点,就可以写程序,按照 NEC 协议驱动红外线发射管,发送数据了。


编写发送程序之前,得先明白这个 38KHZ 的红外光如何产生?


STM32 支持硬件 PWM 功能,可以配置 38KHZ 方波输出;如果没有硬件 PWM 功能的单片机,也可以使用延时的方式产生 38KHZ 方波,差那么一点点问题也不到,解码端适当调整一下时间范围即可。


采用延时函数实现方法如下:


/*函数功能: 发送38KHZ的载波函数参数:u32 time_us 持续的时间u8 flag 1表示发送38KHZ载波,0表示不发送*/void InfraredSend38KHZ(u32 time_us,u8 flag){    u32 i;    if(flag)    {        //发送38KHZ载波        for(i=0;i<time_us/13;i++)        {            INFRARED_OUTPUT=!INFRARED_OUTPUT;            DelayUs(13);        }    }    else    {        INFRARED_OUTPUT=1;//关闭红外线发射管        DelayUs(time_us);    }}
复制代码


为了方便发送指定的用户码和按键码,可以封装成一个函数调用。


/*函数功能: NEC协议编码发送函数参数:         u8 user 用户码        u8 key  按键码先发低位按键反码+按键码+用户反码+用户码*/void InfraredNECSend(u8 user,u8 key){  u32 i;   /*1. 组合发送的数据*/  u32 data=((~key&0xFF)<<24)|((key&0xFF)<<16)|((~user&0xFF)<<8)|((user&0xFF)<<0);       /*2. 发送引导码*/  InfraredSend38KHZ(9000,1);//发送38KHZ载波  InfraredSend38KHZ(4500,0);//不发送    /*3. 发送32位数据*/   for(i=0;i<32;i++)   {      InfraredSend38KHZ(560,1); //间隔时间      if(data&0x01)InfraredSend38KHZ(1685,0); //发送1      else InfraredSend38KHZ(560,0); //发送0      data>>=1;   }   InfraredSend38KHZ(560,1); //间隔时间}
复制代码


这是使用逻辑分析仪采集的发送端波形: 和协议对应了一下,没有问题。



对比一下解码端采集的波形图:


三、核心代码

3.1 main.c


因为文章篇幅限制,不能贴出全部代码,字数超限。需要其他部分的代码可以去这里下载:https://download.csdn.net/download/xiaolong1126626497/19863305

#include "stm32f10x.h"#include "beep.h"#include "delay.h"#include "led.h"#include "key.h"#include "sys.h"#include "usart.h"#include <string.h>#include <stdio.h>#include "exti.h"#include "timer.h"#include "rtc.h"#include "adc.h"#include "ds18b20.h"#include "ble.h"#include "esp8266.h"#include "wdg.h"#include "oled.h"#include "rfid_rc522.h"#include "infrared.h"
int main(){ LED_Init(); KEY_Init(); BEEP_Init(); TIM1_Init(72,20000); //辅助串口1接收,超时时间为20ms USART_X_Init(USART1,72,115200); //InfraredDecodeInit(); //红外线解码初始化 InfraredCodingInit(); //红外线编码初始化 printf("UART1 OK.....\n"); while(1) { InfraredNECSend(13,14); //发送红外线数据 DelayMs(500); LED0=!LED0; }}
复制代码

3.2 红外线.c

#include "infrared.h"
/*函数功能: 红外线编码初始化硬件连接: PG11编码思路: 采用延时函数实现38KHZ*/void InfraredCodingInit(void){ RCC->APB2ENR|=1<<8; //PG GPIOG->CRH&=0xFFFF0FFF; GPIOG->CRH|=0x00003000; GPIOG->ODR|=1<<11;}
/*函数功能: 发送38KHZ的载波函数参数:u32 time_us 持续的时间u8 flag 1表示发送38KHZ载波,0表示不发送*/void InfraredSend38KHZ(u32 time_us,u8 flag){ u32 i; if(flag) { //发送38KHZ载波 for(i=0;i<time_us/13;i++) { INFRARED_OUTPUT=!INFRARED_OUTPUT; DelayUs(13); } } else { INFRARED_OUTPUT=1;//关闭红外线发射管 DelayUs(time_us); }}
/*函数功能: NEC协议编码发送函数参数: u8 user 用户码 u8 key 按键码先发低位按键反码+按键码+用户反码+用户码*/void InfraredNECSend(u8 user,u8 key){ u32 i; /*1. 组合发送的数据*/ u32 data=((~key&0xFF)<<24)|((key&0xFF)<<16)|((~user&0xFF)<<8)|((user&0xFF)<<0); /*2. 发送引导码*/ InfraredSend38KHZ(9000,1);//发送38KHZ载波 InfraredSend38KHZ(4500,0);//不发送 /*3. 发送32位数据*/ for(i=0;i<32;i++) { InfraredSend38KHZ(560,1); //间隔时间 if(data&0x01)InfraredSend38KHZ(1685,0); //发送1 else InfraredSend38KHZ(560,0); //发送0 data>>=1; } InfraredSend38KHZ(560,1); //间隔时间}
复制代码

四、格力空调遥控协议介绍

4.1 协议解析

报头脉冲:9ms


报头间距:4.5ms


载波频率:37.9KHz(38KHz)


码段 1 与码段 2 间距:20ms


“1”:脉宽,656us。间距,1640us。


“0”:脉宽,656us。间距,544us。

4.2 编码定义

1-3 位:模式


送风:图标:风扇。代码:110。


自动:图标:循环箭头。代码:000。


除湿:图标:水滴。代码:010。


制冷:图标:雪花。代码:100。


制热:图标:太阳。代码:001。


4 位(加 68 位):开机关机


开机:1。


关机:0。第 68 位取反。


5-6 位:风速


一级:10


二级:01


三级:11


自动:00


7、37、41 位(加 65 位):扫风


上下扫风:110。第 65 位取反


左右扫风:101。


上下左右:111


无扫风:000


8 位:睡眠


睡眠:1


不睡眠:0


9-12 位与 65-68 位:温度


制冷模式下:



制热模式:



吸湿模式:



送风模式:



13-20 位:睡眠定时



21 位:超强


超强:1


普通:0


22 位:灯光


亮:1


灭:0


23 位与 25 位:健康,换气


健康:10


换气:01


健康+换气:11


普通:00


24 位:制冷模式下-干燥;制热模式下-辅热;


干燥:1


普通:0


45-46 位:显示温度


不显示:00


显示:10


显示室内温度:01


显示室外温度:11


其他位:


除了 29、31、34 位为“1”外,均为“0”。其他位功能不详(遥控器无对应项)。


第 36 位和 69 位分别是码段 1 和码段 2 的最后一位,无所谓“0”“1”。

4.3 其他说明

在自动模式下只可以设置的项目有:风速 1、2、3 级、自动;上上下左右扫风;显示温度;灯光;睡眠定时(非睡眠)。其他项均不可以设置。此时温度不可设置,温度段的代码为:10011101。


在关机状态下,可以设置定时开机,代码与睡眠定时关机一样。也可以设置灯光。


在制冷模式下,可以设置的项有:温度;扫风;健康换气,节能(仅在此状态下可以设置);风速;定时;超强;睡眠;灯光;温度显示。


在除湿模式下,可以设置的项有:温度;扫风;健康换气;干燥;温度显示;定时;睡眠;灯光。


在送风模式下,可以设置的项有:温度;风速;健康换气;扫风;温度显示;定时;灯光。


在制热模式下,可以设置的项有:温度;风速;扫风;辅热;温度显示;定时;超强;睡眠;灯光。


MGQ 2012-04-141、 格力 YB0F2 红外信号命令格式


红外信号主要包括 CMD1 和 CMD2 两部分,其中 CMD1 包括 35 位的命令 和一位停止位,CMD2 包括 32 位的命令和一位停止位。

五、美的空调协议介绍

L 为引导码,


S 为分隔码,


A 为认别码(A=10110010=B2,预留方案时 A=10110111=B7),


A'为 A 的反码,


B'为 B 的反码,


C'为 C 的反码


遥控器发射红外信号之时,通过“560 微秒低电平+1680 微秒高电平”代表“1”,通过“560 微秒低电平+560 微秒低电平”代表“0”。


美的的红外采用 NEC 格式的 R05d


该协议的红外信号编码格式为:引导码+客户码+客户反码+数据码+数据反码+结束位


其中引导码和结束码都是固定的,数据反码由数据码按位取反得来,真正变化的只有用户码和数据码。




发布于: 刚刚阅读数: 3
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
STM32入门开发 制作红外线遥控器(智能居家-万能遥控器)_8月月更_DS小龙哥_InfoQ写作社区