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

Posted DS小龙哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)相关的知识,希望对你有一定的参考价值。

一、环境介绍

MCU: STM32F103ZET6

编程软件环境: keil5

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

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

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

完整keil工程源码下载(解压即可编译运行测试):   

https://download.csdn.net/download/xiaolong1126626497/19863305

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

2.1 NEC协议介绍

NEC协议在上篇<STM32入门开发: 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<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

#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.9KHz38KHz

码段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以上是关于STM32入门开发: 制作红外线遥控器(智能居家-万能遥控器)的主要内容,如果未能解决你的问题,请参考以下文章

STM32入门开发: NEC红外线协议解码(超低成本无线传输方案)

基于STM32的智能家居控制系统设计与实现(带红外遥控控制空调)

基于STM32的智能家居控制系统设计与实现(带红外遥控控制空调)

Velscode的博客导航

STM32解析美的空调红外遥控器

Velscode的博客导航