STM32
直播中

张桂英

7年用户 1535经验值
私信 关注
[问答]

如何用NEC协议模拟家电遥控器对设备进行遥控操作呢

NEC协议是什么?
如何用NEC协议模拟家电遥控器对设备进行遥控操作呢?

回帖(1)

冯栋

2021-11-25 15:59:16
一、环境介绍

MCU: STM32F103ZET6
编程软件环境: keil5
红外线传输协议: NEC协议---38KHZ载波:。NEC协议是红外遥控协议中常见的一种。
编码发送思路: 延时函数模拟38KHZ +  PWM产生38KHZ两种方式
代码风格:   模块化编程,寄存器直接操作方式
完整keil工程源码下载(解压即可编译运行测试):   

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

2.1 NEC协议介绍

NEC协议在上篇文章里已经详细介绍过了。这篇文章和上篇文章内容是连贯的,上篇文章完成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         {
            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


#include "stm32f10x.h"
#include "beep.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include
#include
#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         {
            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位:温度
制冷模式下:

温度
9-12位
65-68位
30
0111
1000
29
1011
0000
28
0011
1111
27
1101
0111
26
0101
1011
25
1001
0011
24
0001
1101
23
1110
0101
22
0110
1001
21
1010
0001
20
0010
1110
19
1100
0110
18
0100
1010
17
1000
0010
16
0000
1100
制热模式:

温度
9-12位
65-68位
30
0111
0010
29
1011
1100
28
1101
0100
27
1101
1000
26
0101
0000
25
1001
1111
24
0001
0111
23
1110
1011
22
0110
0011
21
1010
1101
20
0010
0101
19
1100
1001
18
0100
0001
17
1000
1110
16
0000
0110
吸湿模式:

温度
9-12位
65-68位
30
0111
0100
29
1011
1000
28
0011
0000
27
1101
1111
26
0101
0111
25
1001
1011
24
0001
0011
23
1110
1101
22
0110
0101
21
1010
1001
20
0010
0001
19
1100
1110
18
0100
0110
17
1000
1010
16
0000
0010
送风模式:

温度
9-12位
65-68位
30
0111
1100
29
1011
0100
28
0011
1000
27
1101
0000
26
0101
1111
25
1001
0111
24
0001
1011
23
1110
0011
22
0110
1101
21
1010
0101
20
0010
1001
19
1100
0001
18
0100
1110
17
1000
0110
16
0000
1010
13-20位:睡眠定时

时间
13-20位
0.5
10010000
1
00011000
1.5
10011000
2
00010100
2.5
10010100
3
00011100
3.5
10011100
4
00010010
4.5
10010010
5
00011010
5.5
10011010
6
00010110
6.5
10010110
7
00011110
7.5
10011110
8
00010001
8.5
10010001
9
00011001
9.5
10011001
10
01010000
10.5
11010000
11
01011000
11.5
11011000
12
01010100
12.5
11010100
13
01011100
13.5
11011100
14
01010010
14.5
11010010
15
01011010
15.5
11011010
16
01010110
16.5
11010110
17
01011110
17.5
11011110
18
01010001
18.5
11010001
19
01011001
19.5
11011001
20
00110000
20.5
10110000
21
00111000
21.5
10111000
22
00110100
22.5
10110100
23
00111100
23.5
10111100
24
00110010
0
00000000
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位的命令和一位停止位。
表格 1 CMD1

Bit:1~3
4
5~6
7
8



模式
开关机(CMD2 32bit取反)
风速
是否扫风
是否睡眠



9~12
13~16






温度
睡眠1






17~20
21
22
23
24



睡眠2
超强
灯光
健康
干燥/辅热



25
26
27
28
29
30
31
32
换气
0
0
0
1
0
1
0
33
34
35





0
1
0






表格 2 CMD2

Bit:1
2
3
4
5
6
7
8
上下扫风
0
0
0
左右扫风
0
0
0
9~10
11
12
13
14
15
16

显示温度
0
0
0
0
0
0

17
18
19
20
21
22
23
24
0
0
0
0
0
0
0
0
25
26
27
28
29~32



0
0
0
0
温度



五、美的空调协议介绍

L为引导码,
S为分隔码,
A为认别码(A=10110010=B2,预留方案时A=10110111=B7),
A'为A的反码,
B'为B的反码,
C'为C的反码
遥控器发射红外信号之时,通过“560微秒低电平+1680微秒高电平”代表“1”,通过“560微秒低电平+560微秒低电平”代表“0”。
美的的红外采用NEC格式的R05d
该协议的红外信号编码格式为:引导码+客户码+客户反码+数据码+数据反码+结束位
其中引导码和结束码都是固定的,数据反码由数据码按位取反得来,真正变化的只有用户码和数据码。







举报

更多回帖

发帖
×
20
完善资料,
赚取积分