基于STM32F103c8t6核心板的红外接收设计

最近尝试做一个红外接收装置,看了网上大多数参考文章以后,选了比较通用的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 <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                             //中断控制器分组设置
    Delay_Init();                                                               //systick初始化
    GUA_Infrared_Receiver_Init();
    while(1)
    {
      //根据你自己写的接收处理函数写代码
    }
}

注意事项

  1. 代码原型来源于甜甜的大香瓜-STM32之红外接收,原型存在一点问题,本文为修改后可正常使用的代码。
  2. 本人使用的器件淘宝链接如下:STM32F103C8T6小系统板 单片机 核心板 STM32开发板 学习板 ARM翼盟 HX1838B红外接收模块遥控接收头模块 单片机积木红外接收板,使用时将红外接收头OUT引脚直接连接单片机I/O口即可,不需要另外的元件参与。

猜你喜欢

转载自blog.csdn.net/qq_37168444/article/details/82493162