一、環(huán)境介紹
編程軟件環(huán)境: keil5
紅外線傳輸協(xié)議:??NEC協(xié)議---38KHZ載波:。NEC協(xié)議是紅外遙控協(xié)議中常見的一種。
編碼發(fā)送思路:??延時(shí)函數(shù)模擬38KHZ +? PWM產(chǎn)生38KHZ兩種方式
代碼風(fēng)格:???模塊化編程,寄存器直接操作方式
完整keil工程源碼下載(解壓即可編譯運(yùn)行測(cè)試):?
https://download.csdn.net/download/xiaolong1126626497/19863305
二、NEC協(xié)議與相關(guān)硬件介紹
2.1 NEC協(xié)議介紹
NEC協(xié)議在上篇<STM32入門開發(fā): NEC紅外線協(xié)議解碼(超低成本無線傳輸方案)>文章里已經(jīng)詳細(xì)介紹過了。這篇文章和上篇文章內(nèi)容是連貫的,上篇文章完成NEC紅外線協(xié)議解碼,這篇文章就當(dāng)做遙控器發(fā)送端,發(fā)送自定義數(shù)據(jù)給接收端,完成自定義的數(shù)據(jù)傳輸;也可以模擬家電遙控器,對(duì)電視機(jī)、投影儀、空調(diào)等設(shè)備進(jìn)行遙控操作。
紅外線協(xié)議有很多,本章節(jié)主要是針對(duì)NEC協(xié)議講解,只要把NEC協(xié)議原理搞懂了,其他協(xié)議都是一樣的使用;如果想要模擬空調(diào)遙控器,去控制美的空調(diào)、格力空調(diào)這些設(shè)備,就需要按照美的、格力空調(diào)的協(xié)議發(fā)送;如果不知道協(xié)議長(zhǎng)什么樣,可以將邏輯分析儀插在紅外線接收頭的引腳上,拿個(gè)正常的空調(diào)遙控器對(duì)著接收頭按一下,然后采集數(shù)據(jù)分析,即可得到協(xié)議規(guī)律,然后網(wǎng)絡(luò)上也有空調(diào)按鍵值功能的說明文檔,調(diào)試一下即可。
2. 2 使用的相關(guān)硬件
因?yàn)橐M紅外線遙控器,就需要一個(gè)紅外線發(fā)射管;在學(xué)習(xí)階段,如果不想自己搭建電路,可以買現(xiàn)成的模塊。 買模塊連接也是比較穩(wěn)定,接線也比較簡(jiǎn)單,VCC和GND接好之后,把DAT引腳接到STM32任意一個(gè)IO口上即可,如果想用硬件PWM控制發(fā)送,那么引腳接到STM32的PWM輸出腳即可。
2.3 完成NEC協(xié)議編碼發(fā)送
先看一段紅外線接收頭引腳上采集的NEC協(xié)議的電平: 這是接收端采集的。
紅外線接收頭的硬件特性: (注意: 這里是針對(duì)NEC遙控器協(xié)議來說明),下圖就是當(dāng)前使用的紅外線接收頭。
收到38KHZ的紅外光,IN引腳就輸出低電平;沒有收到IN引腳就輸出高電平。
NEC紅外線協(xié)議說明:(這是站在接收端解碼的角度分析的)
一段獨(dú)立的NEC協(xié)議數(shù)據(jù)包由引導(dǎo)碼+32位數(shù)據(jù)組成。
引導(dǎo)碼:? 9ms的高電平? +? 4.5ms 低電平組成。
32位數(shù)據(jù)就是:? 8位用戶碼+ 8位用戶反碼+ 8位按鍵碼+8位按鍵反碼
每個(gè)數(shù)據(jù)位之間的間隔時(shí)間是0.56ms(低電平)
NEC協(xié)議是依靠收到的高電平持續(xù)時(shí)間來判斷數(shù)據(jù)0和數(shù)據(jù)1;高電平持續(xù)時(shí)間是0.56ms表示數(shù)據(jù)0,高電平持續(xù)時(shí)間是1.68ms表示數(shù)據(jù)1。
只要明白上面說的兩個(gè)特點(diǎn),就可以寫程序,按照NEC協(xié)議驅(qū)動(dòng)紅外線發(fā)射管,發(fā)送數(shù)據(jù)了。
編寫發(fā)送程序之前,得先明白這個(gè)38KHZ的紅外光如何產(chǎn)生?
STM32支持硬件PWM功能,可以配置38KHZ方波輸出;如果沒有硬件PWM功能的單片機(jī),也可以使用延時(shí)的方式產(chǎn)生38KHZ方波,差那么一點(diǎn)點(diǎn)問題也不到,解碼端適當(dāng)調(diào)整一下時(shí)間范圍即可。
采用延時(shí)函數(shù)實(shí)現(xiàn)方法如下:
/*
函數(shù)功能: 發(fā)送38KHZ的載波
函數(shù)參數(shù):
u32 time_us 持續(xù)的時(shí)間
u8 flag 1表示發(fā)送38KHZ載波,0表示不發(fā)送
*/
void InfraredSend38KHZ(u32 time_us,u8 flag)
{
u32 i;
if(flag)
{
//發(fā)送38KHZ載波
for(i=0;i<time_us/13;i++)
{
INFRARED_OUTPUT=!INFRARED_OUTPUT;
DelayUs(13);
}
}
else
{
INFRARED_OUTPUT=1;//關(guān)閉紅外線發(fā)射管
DelayUs(time_us);
}
}
為了方便發(fā)送指定的用戶碼和按鍵碼,可以封裝成一個(gè)函數(shù)調(diào)用。
/*
函數(shù)功能: NEC協(xié)議編碼發(fā)送
函數(shù)參數(shù):
u8 user 用戶碼
u8 key 按鍵碼
先發(fā)低位
按鍵反碼+按鍵碼+用戶反碼+用戶碼
*/
void InfraredNECSend(u8 user,u8 key)
{
u32 i;
/*1. 組合發(fā)送的數(shù)據(jù)*/
u32 data=((~key&0xFF)<<24)|((key&0xFF)<<16)|((~user&0xFF)<<8)|((user&0xFF)<<0);
/*2. 發(fā)送引導(dǎo)碼*/
InfraredSend38KHZ(9000,1);//發(fā)送38KHZ載波
InfraredSend38KHZ(4500,0);//不發(fā)送
/*3. 發(fā)送32位數(shù)據(jù)*/
for(i=0;i<32;i++)
{
InfraredSend38KHZ(560,1); //間隔時(shí)間
if(data&0x01)InfraredSend38KHZ(1685,0); //發(fā)送1
else InfraredSend38KHZ(560,0); //發(fā)送0
data>>=1;
}
InfraredSend38KHZ(560,1); //間隔時(shí)間
}
這是使用邏輯分析儀采集的發(fā)送端波形: 和協(xié)議對(duì)應(yīng)了一下,沒有問題。
對(duì)比一下解碼端采集的波形圖:
三、核心代碼
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接收,超時(shí)時(shí)間為20ms
USART_X_Init(USART1,72,115200);
//InfraredDecodeInit(); //紅外線解碼初始化
InfraredCodingInit(); //紅外線編碼初始化
printf("UART1 OK.....n");
while(1)
{
InfraredNECSend(13,14); //發(fā)送紅外線數(shù)據(jù)
DelayMs(500);
LED0=!LED0;
}
}
3.2 紅外線.c
#include "infrared.h"
/*
函數(shù)功能: 紅外線編碼初始化
硬件連接: PG11
編碼思路: 采用延時(shí)函數(shù)實(shí)現(xiàn)38KHZ
*/
void InfraredCodingInit(void)
{
RCC->APB2ENR|=1<<8; //PG
GPIOG->CRH&=0xFFFF0FFF;
GPIOG->CRH|=0x00003000;
GPIOG->ODR|=1<<11;
}
/*
函數(shù)功能: 發(fā)送38KHZ的載波
函數(shù)參數(shù):
u32 time_us 持續(xù)的時(shí)間
u8 flag 1表示發(fā)送38KHZ載波,0表示不發(fā)送
*/
void InfraredSend38KHZ(u32 time_us,u8 flag)
{
u32 i;
if(flag)
{
//發(fā)送38KHZ載波
for(i=0;i<time_us/13;i++)
{
INFRARED_OUTPUT=!INFRARED_OUTPUT;
DelayUs(13);
}
}
else
{
INFRARED_OUTPUT=1;//關(guān)閉紅外線發(fā)射管
DelayUs(time_us);
}
}
/*
函數(shù)功能: NEC協(xié)議編碼發(fā)送
函數(shù)參數(shù):
u8 user 用戶碼
u8 key 按鍵碼
先發(fā)低位
按鍵反碼+按鍵碼+用戶反碼+用戶碼
*/
void InfraredNECSend(u8 user,u8 key)
{
u32 i;
/*1. 組合發(fā)送的數(shù)據(jù)*/
u32 data=((~key&0xFF)<<24)|((key&0xFF)<<16)|((~user&0xFF)<<8)|((user&0xFF)<<0);
/*2. 發(fā)送引導(dǎo)碼*/
InfraredSend38KHZ(9000,1);//發(fā)送38KHZ載波
InfraredSend38KHZ(4500,0);//不發(fā)送
/*3. 發(fā)送32位數(shù)據(jù)*/
for(i=0;i<32;i++)
{
InfraredSend38KHZ(560,1); //間隔時(shí)間
if(data&0x01)InfraredSend38KHZ(1685,0); //發(fā)送1
else InfraredSend38KHZ(560,0); //發(fā)送0
data>>=1;
}
InfraredSend38KHZ(560,1); //間隔時(shí)間
}
四、格力空調(diào)遙控協(xié)議介紹
4.1 協(xié)議解析
報(bào)頭脈沖:9ms
報(bào)頭間距:4.5ms
載波頻率:37.9KHz(38KHz)
碼段1與碼段2間距:20ms
“1”:脈寬,656us。間距,1640us。
“0”:脈寬,656us。間距,544us。
4.2 編碼定義
1-3位:模式
送風(fēng):圖標(biāo):風(fēng)扇。代碼:110。
自動(dòng):圖標(biāo):循環(huán)箭頭。代碼:000。
除濕:圖標(biāo):水滴。代碼:010。
制冷:圖標(biāo):雪花。代碼:100。
制熱:圖標(biāo):太陽。代碼:001。
4位(加68位):開機(jī)關(guān)機(jī)
開機(jī):1。
關(guān)機(jī):0。第68位取反。
5-6位:風(fēng)速
一級(jí):10
二級(jí):01
三級(jí):11
自動(dòng):00
7、37、41位(加65位):掃風(fēng)
上下掃風(fēng):110。第65位取反
左右掃風(fēng):101。
上下左右:111
無掃風(fēng):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 |
送風(fēng)模式:
溫度 | 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位:睡眠定時(shí)
時(shí)間 | 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位:超強(qiáng)
超強(qiáng):1
普通:0
22位:燈光
亮:1
滅:0
23位與25位:健康,換氣
健康:10
換氣:01
健康+換氣:11
普通:00
24位:制冷模式下-干燥;制熱模式下-輔熱;
干燥:1
普通:0
45-46位:顯示溫度
不顯示:00
顯示:10
顯示室內(nèi)溫度:01
顯示室外溫度:11
其他位:
除了29、31、34位為“1”外,均為“0”。其他位功能不詳(遙控器無對(duì)應(yīng)項(xiàng))。
第36位和69位分別是碼段1和碼段2的最后一位,無所謂“0”“1”。
4.3 其他說明
在自動(dòng)模式下只可以設(shè)置的項(xiàng)目有:風(fēng)速1、2、3級(jí)、自動(dòng);上上下左右掃風(fēng);顯示溫度;燈光;睡眠定時(shí)(非睡眠)。其他項(xiàng)均不可以設(shè)置。此時(shí)溫度不可設(shè)置,溫度段的代碼為:10011101。
在關(guān)機(jī)狀態(tài)下,可以設(shè)置定時(shí)開機(jī),代碼與睡眠定時(shí)關(guān)機(jī)一樣。也可以設(shè)置燈光。
在制冷模式下,可以設(shè)置的項(xiàng)有:溫度;掃風(fēng);健康換氣,節(jié)能(僅在此狀態(tài)下可以設(shè)置);風(fēng)速;定時(shí);超強(qiáng);睡眠;燈光;溫度顯示。
在除濕模式下,可以設(shè)置的項(xiàng)有:溫度;掃風(fēng);健康換氣;干燥;溫度顯示;定時(shí);睡眠;燈光。
在送風(fēng)模式下,可以設(shè)置的項(xiàng)有:溫度;風(fēng)速;健康換氣;掃風(fēng);溫度顯示;定時(shí);燈光。
在制熱模式下,可以設(shè)置的項(xiàng)有:溫度;風(fēng)速;掃風(fēng);輔熱;溫度顯示;定時(shí);超強(qiáng);睡眠;燈光。
MGQ 2012-04-141、?格力YB0F2紅外信號(hào)命令格式
紅外信號(hào)主要包括CMD1和CMD2兩部分,其中CMD1包括35 位的命令 和一位停止位,CMD2包括32位的命令和一位停止位。
表格 1 CMD1
Bit:1~3 | 4 | 5~6 | 7 | 8 | |||
模式 | 開關(guān)機(jī)(CMD2 32bit取反) | 風(fēng)速 | 是否掃風(fēng) | 是否睡眠 | |||
9~12 | 13~16 | ||||||
溫度 | 睡眠1 | ||||||
17~20 | 21 | 22 | 23 | 24 | |||
睡眠2 | 超強(qiáng) | 燈光 | 健康 | 干燥/輔熱 | |||
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 |
上下掃風(fēng) | 0 | 0 | 0 | 左右掃風(fēng) | 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 | 溫度 |
五、美的空調(diào)協(xié)議介紹
L為引導(dǎo)碼,
S為分隔碼,
A為認(rèn)別碼(A=10110010=B2,預(yù)留方案時(shí)A=10110111=B7),
A'為A的反碼,
B'為B的反碼,
C'為C的反碼
遙控器發(fā)射紅外信號(hào)之時(shí),通過“560微秒低電平+1680微秒高電平”代表“1”,通過“560微秒低電平+560微秒低電平”代表“0”。
美的的紅外采用NEC格式的R05d
該協(xié)議的紅外信號(hào)編碼格式為:引導(dǎo)碼+客戶碼+客戶反碼+數(shù)據(jù)碼+數(shù)據(jù)反碼+結(jié)束位,
其中引導(dǎo)碼和結(jié)束碼都是固定的,數(shù)據(jù)反碼由數(shù)據(jù)碼按位取反得來,真正變化的只有用戶碼和數(shù)據(jù)碼。