一、NEC紅外線協議與接收頭介紹
紅外線遙控是家電領域里很常見的一種遙控方式,常見的電視機、空調、投影機等設備基本都支持紅外線遙控;這也主要是紅外線遙控成本比較低,現在很多電視機也支持藍牙遙控器了,穿透性、速度、比紅外線遙控要好很多。
紅外線遙控的原理: 就是通過紅外光的閃爍傳遞數據,需要一對紅外線發射管、一個紅外線接收頭。 這個紅外線接收頭對紅外光很敏感,接收到紅外光就輸出低電平,相反就是高電平。所以可以通過這個原理就可以通過與遙控器端、接收端約定協議就能傳遞數據了。
下面兩張圖是紅外線接收頭的原理圖:
二、解碼實現代碼
紅外線協議有很多,下面就以NEC協議為例: NEC協議分為: 引導碼、用戶碼、用戶反碼、按鍵碼、按鍵反碼組成。 引導碼是9ms低電平+4.5毫秒高電平組成。 數據位一共32位。也就是個字節。對應上面說的后4個數據位。
數據1表示:0.56ms低電平+1.68ms高電平 數據0表示:0.56ms低電平+0.56ms低電平。
紅外線解碼思路在M4上面實現有兩種方式(其實本質是一樣的):
- 通過定時器輸入捕獲方式
- 通過定時器+外部中斷的方式
下面的代碼就是采用定時器捕獲+外部中斷方式實現解碼。
2.1 main.c代碼
#include "stm32f4xx.h" // Device header
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include "sys.h"
#include "exti.h"
#include "timer.h"
#include "pwm.h"
#include "ds18b20.h"
#include "infrared.h"
extern u8 InfraredRxBuff[5];
int main(void)
{
LED_Init();
KEY_Init();
USART1_Init(84,115200);
KEY_EXTI_Init();
DS18B20_Init();
InfraredRxInit(); //紅外線解碼初始化
while(1)
{
if(InfraredRxBuff[4])
{
InfraredRxBuff[4]=0; //清除接收成功標志
printf("USER=0x%x\r\n",InfraredRxBuff[0]);
printf("KEY=0x%x\r\n",InfraredRxBuff[2]);
LED0=0;
DelayMs(100);
LED0=1;
}
}
}
復制代碼
2.2 解碼核心代碼
#include "infrared.h"
/*
函數功能:紅外線解碼初始化
硬件連接:PA8
定 時 器:使用TIM2
*/
void InfraredRxInit(void)
{
/*1. 開時鐘*/
RCC->AHB1ENR|=1<<0;//使能PORTA時鐘
/*2. 配置GPIO口模式*/
GPIOA->MODER&=~(0x3<<8*2); //清除模式
GPIOA->MODER|=0x0<<8*2; //配置輸入模式
/*3. 開啟SYSCFG時鐘 */
RCC->APB2ENR|=1<<14;
/*4. 開放來自線x上的中斷請求*/
EXTI->IMR|=1<<8; //中斷線8
/*3. 配置中斷線觸發邊沿*/
EXTI->FTSR|=1<<8; //下降沿
/*4. 配置產生中斷的對應IO口*/
SYSCFG->EXTICR[2]&=~(0xf<<0*4);
SYSCFG->EXTICR[2]|=0x0<<0*4;
/*5. 配置中斷優先級*/
SetNVICPriorityGrouping(EXTI9_5_IRQn,1,1);
/*6. 初始化定時器*/
RCC->APB1ENR|=1<<0; //開啟定時器2的時鐘
RCC->APB1RSTR|=1<<0; //開啟復位時鐘
RCC->APB1RSTR&=~(1<<0); //關閉
TIM2->PSC=84; //預分頻
TIM2->ARR=65535; //重裝載寄存器
TIM2->CR1&=~(1<<0); //開啟計數器
}
/*
函數功能:獲取高電平持續的時間
返 回 值:高電平持續的時間
*/
u32 GetInfraredRxH(void)
{
TIM2->CR1|=1<<0;
TIM2->CNT=0;
while(INFRARED_RX){}
TIM2->CR1&=~(1<<0);
return TIM2->CNT;
}
/*
函數功能:獲取低電平持續的時間
返 回 值:低電平持續的時間
*/
u32 GetInfraredRxL(void)
{
TIM2->CR1|=1<<0;
TIM2->CNT=0;
while(!INFRARED_RX){}
TIM2->CR1&=~(1<<0);
return TIM2->CNT;
}
/*
函數功能:外部中斷線0中斷服務函數
NEC協議解碼原理:
1. 先接收引導碼:9ms低電平+4.5ms高電平
2. 引導碼之后,是連續的32位數據。用戶碼+用戶反碼+按鍵碼+按鍵反碼
3. 數據‘0’ :560us低電平+560us高電平
4. 數據‘1’ :560us低電平+1680us高電平
*/
u8 InfraredRxBuff[5]={0}; //存放紅外線接收的數據值,其中[4]表示標志位。=0失敗,=1成功
void EXTI9_5_IRQHandler(void)
{
u32 time,j,i;
u8 data=0;
EXTI->PR|=1<<0; //清除中斷標志位
/*1. 判斷引導碼*/
time=GetInfraredRxL(); //獲取低電平的時間
if(time<5000||time>11000)return;
time=GetInfraredRxH();
if(time<2500||time>5500)return;
/*2. 接收用戶碼和按鍵碼*/
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
time=GetInfraredRxL(); //獲取低電平的時間
if(time<360||time>660)return;
time=GetInfraredRxH(); //獲取高電平的時間
//560us高電平 0 、 1680us高電平 1
if(time>360&&time<660)
{
data>>=1;
}
else if(time>1480&&time<1880)
{
data>>=1;
data|=0x80; //1000 0000
}
}
InfraredRxBuff[i]=data;
}
InfraredRxBuff[4]=1; //標志紅外線解碼成功
}
#ifndef _INFRARED_H
#define _INFRARED_H
#include "stm32f4xx.h"
#include "sys.h"
void InfraredRxInit(void);
u32 GetInfraredRxH(void);
u32 GetInfraredRxL(void);
#define INFRARED_RX PAin(8) //紅外線的接收口
#endif
審核編輯:湯梓紅
-
紅外線
+關注
關注
14文章
619瀏覽量
56176 -
NEC
+關注
關注
0文章
238瀏覽量
99110 -
STM32F407
+關注
關注
15文章
187瀏覽量
29437
發布評論請先 登錄
相關推薦
評論