一、环境介绍
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
该协议的红外信号编码格式为:引导码+客户码+客户反码+数据码+数据反码+结束位,
其中引导码和结束码都是固定的,数据反码由数据码按位取反得来,真正变化的只有用户码和数据码。