最近尝试做一个红外接收装置,看了网上大多数参考文章以后,选了比较通用的NEC红外协议入手,正巧有一个遥控器使用的正是NEC协议,解决了信号源问题,我的目标便是用STM32c8t6核心板配合集成红外接收头将遥控器各个按键识别出来,大致思路是利用STM32外部中断引脚接收信号,利用延时并根据NEC协议判断起始码、地址码地址反码、用户码、用户反码,具体实现代码如下:
红外接收函数GUA_Infrared_Receiver.c
#include "stm32f10x.h"
#include "GUA_Infrared_Receiver.h"
#include "delay.h"
#define TRUE 0
#define FALSE 1
#define GUA_INFRARED_RECEIVER_PORT GPIOB
#define GUA_INFRARED_RECEIVER_PIN GPIO_Pin_5
#define GUA_INFRARED_RECEIVER_RCC RCC_APB2Periph_GPIOB
#define GUA_INFRARED_RECEIVER_EXTI_LINE EXTI_Line5
#define GUA_INFRARED_RECEIVER_PORTSOURCE GPIO_PortSourceGPIOB
#define GUA_INFRARED_RECEIVER_PINSOURCE GPIO_PinSource5
GUA_U32 gGUA_InfraredReceiver_Data = 0;
static void GUA_Infrared_Receiver_IO_Init(void);
static GUA_U16 GUA_Infrared_Receiver_GetHighLevelTime(void);
static GUA_U16 GUA_Infrared_Receiver_GetLowLevelTime(void);
u8 IR_RECEIVE[5];
int down16,up16;
static void GUA_Infrared_Receiver_IO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(GUA_INFRARED_RECEIVER_RCC | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GUA_INFRARED_RECEIVER_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GUA_INFRARED_RECEIVER_PORT, &GPIO_InitStructure);
GPIO_EXTILineConfig(GUA_INFRARED_RECEIVER_PORTSOURCE, GUA_INFRARED_RECEIVER_PINSOURCE);
}
//******************************************************************************
//name: GUA_Infrared_Receiver_Exti_Init
//******************************************************************************
static void GUA_Infrared_Receiver_Exti_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = GUA_INFRARED_RECEIVER_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//******************************************************************************
//name: GUA_Infrared_Receiver_Init
//******************************************************************************
void GUA_Infrared_Receiver_Init(void)
{
GUA_Infrared_Receiver_IO_Init();
GUA_Infrared_Receiver_Exti_Init();
}
//******************************************************************************
//name: GUA_Infrared_Receiver_GetHighLevelTime
//******************************************************************************
static GUA_U16 GUA_Infrared_Receiver_GetHighLevelTime(void)
{
GUA_U16 nGUA_Num = 0;
while(GPIO_ReadInputDataBit(GUA_INFRARED_RECEIVER_PORT, GUA_INFRARED_RECEIVER_PIN) == Bit_SET)
{
if(nGUA_Num >= 250)
{
return nGUA_Num;
}
nGUA_Num++;
DelayUs(12);//该延时针对外部晶振8000的STM32C8T6核心板,对于不同类型不同外部晶振的开发板需要根据波形图调整延时,保证20us延时
}
return nGUA_Num;
}
//******************************************************************************
//name: GUA_Infrared_Receiver_GetLowLevelTime
//******************************************************************************
static GUA_U16 GUA_Infrared_Receiver_GetLowLevelTime(void)
{
GUA_U16 nGUA_Num = 0;
while(GPIO_ReadInputDataBit(GUA_INFRARED_RECEIVER_PORT, GUA_INFRARED_RECEIVER_PIN) == Bit_RESET)
{
if(nGUA_Num >= 500)
{
return nGUA_Num;
}
nGUA_Num++;
DelayUs(12);//该延时针对外部晶振8000的STM32C8T6核心板,对于不同类型不同外部晶振的开发板需要根据波形图调整延时,保证20us延时
}
return nGUA_Num;
}
//******************************************************************************
//name: GUA_Infrared_Receiver_Process
//******************************************************************************
GUA_U8 GUA_Infrared_Receiver_Process(void)
{
GUA_U16 nGUA_Time_Num = 0;
GUA_U8 nGUA_Data = 0;
GUA_U8 nGUA_Byte_Num = 0;
GUA_U8 nGUA_Bit_Num = 0;
nGUA_Time_Num = GUA_Infrared_Receiver_GetLowLevelTime();
t0=nGUA_Time_Num;
if((nGUA_Time_Num >= 500) || (nGUA_Time_Num <= 400))
{
return GUA_INFRARED_RECEIVER_ERROR;
}
nGUA_Time_Num = GUA_Infrared_Receiver_GetHighLevelTime();
if((nGUA_Time_Num >= 250) || (nGUA_Time_Num <= 200))
{
return GUA_INFRARED_RECEIVER_ERROR;
}
for(nGUA_Byte_Num = 0; nGUA_Byte_Num < 4; nGUA_Byte_Num++)
{
for(nGUA_Bit_Num = 0; nGUA_Bit_Num < 8; nGUA_Bit_Num++)
{
nGUA_Time_Num = GUA_Infrared_Receiver_GetLowLevelTime();
if((nGUA_Time_Num >= 60) || (nGUA_Time_Num <= 20))
{
return GUA_INFRARED_RECEIVER_ERROR;
}
nGUA_Time_Num = GUA_Infrared_Receiver_GetHighLevelTime();
if((nGUA_Time_Num >=60) && (nGUA_Time_Num < 100))
{
nGUA_Data = 1;
}
else if((nGUA_Time_Num >=10) && (nGUA_Time_Num < 50))
{
nGUA_Data = 0;
}
else
{
return GUA_INFRARED_RECEIVER_ERROR;
}
gGUA_InfraredReceiver_Data <<= 1;
gGUA_InfraredReceiver_Data |= nGUA_Data;
}
}
return GUA_INFRARED_RECEIVER_OK;
}
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(GUA_INFRARED_RECEIVER_EXTI_LINE) != RESET)
{
EXTI_ClearITPendingBit(GUA_INFRARED_RECEIVER_EXTI_LINE);
EXTI->IMR &= ~(GUA_INFRARED_RECEIVER_EXTI_LINE);
if(GUA_Infrared_Receiver_Process() == GUA_INFRARED_RECEIVER_OK)
{
down16=gGUA_InfraredReceiver_Data;
up16=gGUA_InfraredReceiver_Data>>16;
//从上到下依次为用户反码、用户码、地址反码、地址码
IR_RECEIVE[3]=down16;
IR_RECEIVE[2]=(down16>>8);
IR_RECEIVE[1]=up16;
IR_RECEIVE[0]=(up16>>8);
//IR_RECPRO();自己写接收处理函数
}
else
{
gGUA_InfraredReceiver_Data=0;
}
}
EXTI->IMR|=(GUA_INFRARED_RECEIVER_EXTI_LINE);
}
红外接收头文件GUA_Infrared_Receiver.h
//******************************************************************************
//name: GUA_Infrared_Receiver.h
//******************************************************************************
#ifndef _GUA_INFRARED_RECEIVER_H_
#define _GUA_INFRARED_RECEIVER_H_
#ifndef GUA_U8
typedef unsigned char GUA_U8;
#endif
#ifndef GUA_8
typedef signed char GUA_8;
#endif
#ifndef GUA_U16
typedef unsigned short GUA_U16;
#endif
#ifndef GUA_16
typedef signed short GUA_16;
#endif
#ifndef GUA_U32
typedef unsigned long GUA_U32;
#endif
#ifndef GUA_32
typedef signed long GUA_32;
#endif
#ifndef GUA_U64
typedef unsigned long long GUA_U64;
#endif
#ifndef GUA_64
typedef signed long long GUA_64;
#endif
#define GUA_INFRARED_RECEIVER_OK 0
#define GUA_INFRARED_RECEIVER_ERROR 1
extern GUA_U32 gGUA_InfraredReceiver_Data;
extern void GUA_Infrared_Receiver_Init(void);
extern GUA_U8 GUA_Infrared_Receiver_Process(void);
void IR_RECPRO(void);
#endif
延时函数及其头文件可参考我的博客基于STM32F103与MY2480-16P语音模块的时钟兼闹钟设计(第一部分)
以下是测试代码main.c
//单片机头文件
#include "stm32f10x.h"
//硬件驱动
#include "delay.h"
#include "GUA_Infrared_Receiver.h"
//C库
#include
#include
#include
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断控制器分组设置
Delay_Init(); //systick初始化
GUA_Infrared_Receiver_Init();
while(1)
{
//根据你自己写的接收处理函数写代码
}
}