STM32F407入门开发: NEC红外线协议解码

2024-06-17  

一、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%xrn",InfraredRxBuff[0]);

printf("KEY=0x%xrn",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


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。