?
一、環(huán)境介紹
紅外線傳輸協(xié)議: NEC協(xié)議---38KHZ載波:。NEC協(xié)議是紅外遙控協(xié)議中常見的一種。
解碼思路: 外部中斷 + 定時器方式
代碼風(fēng)格: 模塊化編程,寄存器直接操作方式
二、NEC協(xié)議與解碼思路介紹
2.1 采用的相關(guān)硬件
圖1: 這是NEC協(xié)議的紅外線遙控器: 如果自己手機沒有紅外線遙控器的功能,可以淘寶上買一個小遙控器來學(xué)習(xí)測試,成本不高,這個遙控器也可以自己做,能解碼當然也可以編碼發(fā)送,只需要一個紅外光發(fā)射管即可。
?
圖2: 這是紅外線接收頭模塊。如果自己的開發(fā)板沒有自帶這個接收頭,那就單獨買一個接收頭模塊,使用杜邦線接到開發(fā)板的IO口上即可用來測試學(xué)習(xí),接線很方便。
?
?
圖3: 這是紅外線發(fā)射管,如果自己想做遙控器的發(fā)射端,自己做遙控器,那么就可以直接購買這種模塊即可。
?
2.2 紅外線協(xié)議介紹
在光譜中波長自760nm至400um的電磁波稱為紅外線,它是一種不可見光。紅外線通信的例子我們每個人應(yīng)該都很熟悉,目前常用的家電設(shè)備幾乎都可以通過紅外遙控的方式進行遙控,比如電視機、空調(diào)、投影儀等,都可以見到紅外遙控的影子。這種技術(shù)應(yīng)用廣泛,相應(yīng)的應(yīng)用器件都十分廉價,因此紅外遙控是我們?nèi)粘TO(shè)備控制的理想方式。
紅外線的通訊原理: 紅外光是以特定的頻率脈沖形式發(fā)射,接收端收到到信號后,按照約定的協(xié)議進行解碼,完成數(shù)據(jù)傳輸,在消費類電子產(chǎn)品里,脈沖頻率普遍采用 30KHz 到 60KHz 這個頻段,NEC協(xié)議的頻率就是38KHZ。 這個以特定的頻率發(fā)射其實就可以理解為點燈,不要被復(fù)雜的詞匯難住了,就是控制燈的閃爍頻率(亮滅),和剛學(xué)單片機完成閃光燈一樣的意思,只不過是燈換了一種類型,都是燈。 接收端的原理: 接收端的芯片對這個紅外光比較敏感,可以根據(jù)有沒有光輸出高低電平,如果發(fā)送端的閃爍頻率是有規(guī)律的,接收端收到后輸出的高電平和低電平也是有規(guī)律對應(yīng)的,這樣發(fā)送端和接收端只要約定好,那就可以做數(shù)據(jù)傳輸了。
紅外線傳輸協(xié)議可以說是所有無線傳輸協(xié)議里成本最低,最方便的傳輸協(xié)議了,但是也有缺點,距離不夠長,速度不夠快;當然,每個傳輸協(xié)議應(yīng)用的環(huán)境不一樣,定位不一樣,好壞沒法比較,具體要看自己的實際場景選擇合適的通信方式。
2.3 NEC協(xié)議介紹
NEC協(xié)議是眾多紅外線協(xié)議中的一種(這里說的協(xié)議就是他們數(shù)據(jù)幀格式定義不一樣,數(shù)據(jù)傳輸原理都是一樣的),我們購買的外能遙控器、淘寶買的mini遙控器、電視機、投影儀幾乎都是NEC協(xié)議。 像格力空調(diào)、美的空調(diào)這些設(shè)備使用的就是其他協(xié)議格式,不是NEC協(xié)議,但是只要學(xué)會一種協(xié)議解析方式,明白了紅外線傳輸原理,其他遙控器協(xié)議都可以解出來。
下圖是NEC協(xié)議傳輸一次數(shù)據(jù)的完整格式:
?
NEC協(xié)議一次完整的傳輸包含: 引導(dǎo)碼、8位用戶碼、8位用戶反碼、8位數(shù)據(jù)碼、8位數(shù)據(jù)反碼。
(注意:下面的解釋都是站在紅外線接收端的角度來進行說明的,就是解碼端的角度)
引導(dǎo)碼: 由9ms的高電平+4.5ms的低電平組成。
4個字節(jié)的數(shù)據(jù): 用戶碼+用戶反碼+數(shù)據(jù)碼+數(shù)據(jù)反碼。 這里的反碼可以用來校驗數(shù)據(jù)是否傳輸正確,有沒有丟包。
重點: NEC協(xié)議傳輸數(shù)據(jù)位的時候,0和1的區(qū)分是依靠收到的高、低電平的持續(xù)時間來進行區(qū)分的---這是解碼關(guān)鍵。
標準間隔時間:0.56ms
收到數(shù)據(jù)位0: 0.56ms
收到位1: 1.68ms
所以,收到一個數(shù)據(jù)位的完整時間表示方法是這樣的:
收到數(shù)據(jù)位0: 0.56m低電平+ 0.56ms的高電平
收到數(shù)據(jù)位1: 0.56ms低電平+1.68ms的高電平
紅外線接收頭模塊輸出電平的原理: 紅外線接收頭感應(yīng)到有紅外光就輸出低電平,沒有感應(yīng)到紅外光就輸出高電平。
這是使用邏輯分析采集紅外線接收頭輸出的信號:
?
這是采集紅外線遙控器上的LED燈輸出電平時序圖,剛好和接收端相反:
?
單片機編寫解碼程序的時候,常見的方式就是采用外部中斷+定時器的方式進行解析,中斷可以設(shè)置為低電平觸發(fā),因為接收頭沒有感應(yīng)到紅外光默認是輸出高電平,如果收到NEC引導(dǎo)碼,就會輸出低電平,進入到中斷服務(wù)函數(shù),完成解碼,解碼過程中開啟定時器記錄每一段的高電平、低電平的持續(xù)時間,按照NEC協(xié)議進行判斷,完成最終解碼。
STM32可以使用輸入捕獲方式完成解碼,其實輸入捕獲就是外部中斷+定時器的組合,只不過是STM32內(nèi)部封裝了一層。
完整keil工程源碼下載(解壓即可編譯運行測試):
https://download.csdn.net/download/xiaolong1126626497/19863275
外部中斷服務(wù)器里的解碼程序如下(這個在其他單片機上思路是一樣的):
/*
函數(shù)功能: 外部中斷線9_5服務(wù)函數(shù)
*/
void EXTI9_5_IRQHandler(void)
{
u32 time;
u8 i,j,data=0;
//清除中斷線9上的中斷請求
EXTI->PR|=1<<9;
time=Infrared_GetTime_L(); //得到低電平時間
if(time<7000||time>10000)return; //標準時間: 9000us
time=Infrared_GetTime_H(); //得到高電平時間
if(time<3000||time>5500)return; //標準時間4500us
//正式解碼NEC協(xié)議
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
time=Infrared_GetTime_L(); //得到低電平時間
if(time<400||time>700)return; //標準時間: 560us
time=Infrared_GetTime_H(); //得到高電平時間
if(time>1400&&time<1800) //數(shù)據(jù)1 1680us
{
data>>=1;
data|=0x80;
}
else if(time>400&&time<700) //數(shù)據(jù)0 560us
{
data>>=1;
}
else return;
}
InfraredRecvData[i]=data; //存放解碼成功的值
}
//解碼成功
InfraredRecvState=1;
}
三、核心完整代碼
?
?
本程序的解碼思路是: 將紅外線接收模塊的輸出腳接到STM32的PB9上,配置STM32的PB9為外部中斷模式,下降沿電平觸發(fā);如果收到紅外線信號就進入到中斷服務(wù)函數(shù)里解碼,如果解碼過程中發(fā)現(xiàn)數(shù)據(jù)不符合要求就終止解碼,如果數(shù)據(jù)全部符合要求就按照協(xié)議接收,直到解碼完成,設(shè)置標志位,在main函數(shù)里打印解碼得到的數(shù)據(jù)。
代碼都是模塊化編程,閱讀起來也很方便。
3.1 紅外線解碼.c
#include "nec_Infrared.h"
u8 InfraredRecvData[4]; //存放紅外線解碼接收的數(shù)據(jù)
u8 InfraredRecvState=0; //0表示未接收到數(shù)據(jù),1表示接收到數(shù)據(jù)
/*
函數(shù)功能: 紅外線解碼初始化(接收)
*/
void Infrared_RecvInit(void)
{
Infrared_Time6_Init(); //定時器初始化
/*1. 配置GPIO口*/
RCC->APB2ENR|=1<<3; //PB
GPIOB->CRH&=0xFFFFFF0F;
GPIOB->CRH|=0x00000080;
GPIOB->ODR|=1<<9;
/*2. 配置外部中斷*/
EXTI->IMR|=1<<9; //外部中斷線9,開放中斷線的中斷請求功能
EXTI->FTSR|=1<<9; //中斷線9_下降沿
RCC->APB2ENR|=1<<0; //開啟AFIO時鐘
AFIO->EXTICR[2]&=~(0xF<<1*4);
AFIO->EXTICR[2]|=0x1<<1*4;
STM32_NVIC_SetPriority(EXTI9_5_IRQn,1,1);
}
/*
函數(shù)功能: 初始化定時器,用于紅外線解碼
*/
void Infrared_Time6_Init(void)
{
RCC->APB1ENR|=1<<4;
RCC->APB1RSTR|=1<<4;
RCC->APB1RSTR&=~(1<<4);
TIM6->PSC=72-1; //預(yù)分頻器
TIM6->ARR=65535; //重裝載寄存器
TIM6->CR1|=1<<7; //開啟緩存功能
//TIMx->CR1|=1<<0; //開啟定時器
}
/*
函數(shù)功能: 測量高電平持續(xù)的時間
*/
u32 Infrared_GetTime_H(void)
{
TIM6->CNT=0;
TIM6->CR1|=1<<0; //開啟定時器
while(NEC_IR){} //等待高電平結(jié)束
TIM6->CR1&=~(1<<0); //關(guān)閉定時器
return TIM6->CNT;
}
/*
函數(shù)功能: 測量低電平持續(xù)的時間
*/
u32 Infrared_GetTime_L(void)
{
TIM6->CNT=0;
TIM6->CR1|=1<<0; //開啟定時器
while(!NEC_IR){} //等待低電平結(jié)束
TIM6->CR1&=~(1<<0); //關(guān)閉定時器
return TIM6->CNT;
}
/*
函數(shù)功能: 外部中斷線9_5服務(wù)函數(shù)
*/
void EXTI9_5_IRQHandler(void)
{
u32 time;
u8 i,j,data=0;
//清除中斷線9上的中斷請求
EXTI->PR|=1<<9;
time=Infrared_GetTime_L(); //得到低電平時間
if(time<7000||time>10000)return; //標準時間: 9000us
time=Infrared_GetTime_H(); //得到高電平時間
if(time<3000||time>5500)return; //標準時間4500us
//正式解碼NEC協(xié)議
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
time=Infrared_GetTime_L(); //得到低電平時間
if(time<400||time>700)return; //標準時間: 560us
time=Infrared_GetTime_H(); //得到高電平時間
if(time>1400&&time<1800) //數(shù)據(jù)1 1680us
{
data>>=1;
data|=0x80;
}
else if(time>400&&time<700) //數(shù)據(jù)0 560us
{
data>>=1;
}
else return;
}
InfraredRecvData[i]=data; //存放解碼成功的值
}
//解碼成功
InfraredRecvState=1;
}
3.2 主函數(shù).c
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include "at24c02.h"
#include "W25Q64.h"
#include "spi.h"
#include "nec_Infrared.h"
int main()
{
LED_Init();
BEEP_Init();
KeyInit();
USARTx_Init(USART1,72,115200);
IIC_Init();
W25Q64_Init();
printf("芯片ID號:0x%X\n",W25Q64_ReadID());
Infrared_RecvInit();
while(1)
{
if(InfraredRecvState)
{
InfraredRecvState=0;
printf("用戶碼:%d,按鍵碼:%d\n",InfraredRecvData[0],InfraredRecvData[2]);
printf("user反碼:%d,key反碼:%d\n",(~InfraredRecvData[1])&0xFF,(~InfraredRecvData[3])&0xFF);
BEEP=!BEEP;
LED0=!LED0;
}
}
}
四、擴展提高
如果上面的NEC的解碼思路已經(jīng)看到,程序已經(jīng)可以自己編寫,就可以試著使用STM32的輸入捕獲+定時器方式寫一版解碼代碼,既能更加熟悉NEC協(xié)議、也可以學(xué)習(xí)STM32定時器捕獲捕獲的用法;也可以做一些小東西來鍛煉,比如:紅外線遙控小車、音樂播放器支持紅外線遙控器切歌,電機的開關(guān)、燈的開關(guān)等等。
搞定協(xié)議解碼之后,我們下一步就是完成自定義的NEC協(xié)議紅外線制作,采用STM32模擬一個萬能紅外線遙控器。
審核編輯:湯梓紅
在光譜中波長自760nm至400um的電磁波稱為紅外線,它是一種不可見光。目前幾乎所有的視頻和音頻設(shè)備都可以通過紅外遙控的方式進行遙控,比如電視機、空調(diào)、影碟機等,都可以見到紅外遙控的影子。這種技術(shù)應(yīng)用廣泛,相應(yīng)的應(yīng)用器件都十分廉價,因此紅外遙控是我們?nèi)粘TO(shè)備控制的理想方式。
?
-
mcu
+關(guān)注
關(guān)注
146文章
17148瀏覽量
351213 -
STM32
+關(guān)注
關(guān)注
2270文章
10900瀏覽量
356046 -
無線傳輸
+關(guān)注
關(guān)注
3文章
569瀏覽量
41028
發(fā)布評論請先 登錄
相關(guān)推薦
評論