Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Introduction of NEC infrared protocol and receiver
Infrared remote control is a very common remote control in the field of home appliances, common TELEVISION, air conditioning, projector and other equipment are basically support infrared remote control; This is mainly due to the low cost of infrared remote control, now many TV sets also support bluetooth remote control, penetration, speed, much better than infrared remote control.
The principle of infrared remote control: it is to transmit data through the flicker of infrared light, which requires a pair of infrared transmitting tubes and an infrared receiving head. This infrared receiver is sensitive to infrared light, and when it receives infrared light, it outputs low level, and vice versa. So you can use this principle and you can use the protocol with the remote control side and the receiver side to transfer data.
The following two diagrams are schematic diagrams of the infrared receiver head:
Second, decoding implementation code
There are many infrared protocols, the following takes NEC protocol as an example: NEC protocol is divided into: boot code, user code, user inverse code, key code, key inverse code. The boot code is 9ms low level + 4.5ms high level. The data bit is 32 bits. That’s a byte. Correspond to the last four data bits mentioned above.
Data 1 indicates 0.56ms low level +1.68ms high level. Data 0 indicates 0.56ms low level +0.56ms low level.
There are two ways to achieve infrared decoding in M4 (in fact, the essence is the same) :
- Input capture mode through timer
- Through timer + external interrupt mode
The following code is the use of timer capture + external interrupt way to achieve decoding.
2.1 the main c code
#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(a);KEY_Init(a);USART1_Init(84.115200);
KEY_EXTI_Init(a);DS18B20_Init(a);InfraredRxInit(a);// Infrared decoder initialization
while(1)
{
if(InfraredRxBuff[4])
{
InfraredRxBuff[4] =0; // Clear the receiving success flag
printf("USER=0x%x\r\n",InfraredRxBuff[0]);
printf("KEY=0x%x\r\n",InfraredRxBuff[2]);
LED0=0;
DelayMs(100);
LED0=1; }}}Copy the code
2.2 Decoding the core code
#include "infrared.h"
/* Function function: infrared decoder initialization hardware connection: PA8 timer: use TIM2 */
void InfraredRxInit(void)
{
/*1. Start the clock */
RCC->AHB1ENR|=1<<0;// Enable the PORTA clock
/*2. Configure the GPIO port mode */
GPIOA->MODER&=~(0x3<<8*2); // Clear mode
GPIOA->MODER|=0x0<<8*2; // Configure the input mode
/*3. Enable SYSCFG clock */
RCC->APB2ENR|=1<<14;
/*4. Open interrupt requests from line x */
EXTI->IMR|=1<<8; // Break line 8
/*3. Configure the interrupt trigger edge */
EXTI->FTSR|=1<<8; Falling edge / /
/*4. Configure the CORRESPONDING I/O port */
SYSCFG->EXTICR[2] & = ~ (0xf<<0*4);
SYSCFG->EXTICR[2] | =0x0<<0*4;
/*5. Set the interrupt priority */
SetNVICPriorityGrouping(EXTI9_5_IRQn,1.1);
/*6. Initialize the timer */
RCC->APB1ENR|=1<<0; // Start the clock of timer 2
RCC->APB1RSTR|=1<<0; // Enable the reset clock
RCC->APB1RSTR&=~(1<<0); / / close
TIM2->PSC=84; / / preassigned frequency
TIM2->ARR=65535; // Reload the register
TIM2->CR1&=~(1<<0); // Turn on the counter
}
/* The return value is the high level duration */
u32 GetInfraredRxH(void)
{
TIM2->CR1|=1<<0;
TIM2->CNT=0;
while(INFRARED_RX){}
TIM2->CR1&=~(1<<0);
return TIM2->CNT;
}
/* The return value is the low level duration */
u32 GetInfraredRxL(void)
{
TIM2->CR1|=1<<0;
TIM2->CNT=0;
while(! INFRARED_RX){} TIM2->CR1&=~(1<<0);
return TIM2->CNT;
}
/* Function function: external interrupt line 0 interrupt service function NEC protocol decoding principle: 1. First receive boot code: 9ms low level +4.5ms high level 2. After boot code, it is continuous 32-bit data. User code + User inverse code + key code + Key inverse code 3. Data '0' : 560us low level +560us high level 4. Data '1' : 560us low +1680us high */
u8 InfraredRxBuff[5] = {0}; // Store infrared received data value, where [4] represents the flag bit. =0 failed, =1 succeeded
void EXTI9_5_IRQHandler(void)
{
u32 time,j,i;
u8 data=0;
EXTI->PR|=1<<0; // Clear the interrupt flag bit
/*1. Check the boot code */
time=GetInfraredRxL(a);// Get the time of low level
if(time<5000||time>11000)return;
time=GetInfraredRxH(a);if(time<2500||time>5500)return;
/*2. Receive the user code and key code */
for(i=0; i<4; i++) {for(j=0; j<8; j++) { time=GetInfraredRxL(a);// Get the time of low level
if(time<360||time>660)return;
time=GetInfraredRxH(a);// The time to get the high level
//560us high level 0, 1680us high level 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; // Signal infrared decoded successfully
}
#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) // Infrared receiver port
#endif
Copy the code