小米遥控器红外接收解码

2019-07-21 06:53发布

忙了一天终于用STM32F207完成小米遥控器的红外接收,块下班了先贴个源码占个坑,有空再续写。楼主脑残,画板子时候红外接收引脚没有连接到定时器上。只能开一个电平中断,在开个定时器中断在电平中断 控制定时器。
[mw_shl_code=c,true]
#ifndef _IR_MI_H
#define _IR_MI_H

/*Includes -------------------------------------------------------------------------------*/
#include "stm32f2xx.h"
#include "FreeRTOS.h"
#include "queue.h"
/* marco ---------------------------------------------------------------------------------*/
/*数据帧高电平长度等效数据 每个数据帧以2bit表示*/
#define IR_FOURTEEN_VALUE    0x03
#define IR_ELEVEN_VALUE      0x02
#define IR_EIGHT_VALUE       0x01
#define IR_FIVE_VALUE        0x00

/*红外脉冲长度单位us*/
#define IR_LEAD_L            1050
#define IR_LEAD_H            550
#define IR_DATA_IDLE_L       650
#define IR_DATA_FOURTEEN_H   1450
#define IR_DATA_ELEVEN_H     1150
#define IR_DATA_EIGHT_H      850
#define IR_DATA_FIVE_H       585
/*红外脉冲测量精度*/
#define IR_MEAS_ACCURACY     100

/*红外接收状态*/
#define IR_STATE_IDLE        0x00
#define IR_STATE_LEAD_ON     0x01
#define IR_STATE_LEAD_OFF    0x02
#define IR_STATE_DATA_IDLE   0x03
#define IR_STATE_DATA        0x04
#define IR_STATE_END                 0x05

/*单次的数据长度*/
#define IR_DATA_LENGTH       10
/*按键用户数据位(前六个数据脉冲)等效值*/
#define IR_CUSTOM_DATA       0x0860
/*OFF前六个数据脉冲等效值*/
#define IR_CUSTOM_OFF        0x03CC
/*按键的等效值*/
#define IR_OFF               0xCF
#define IR_UP                0x5B
#define IR_DOWN              0x68
#define IR_LEFT              0xB5
#define IR_RIGHT             0xC2
#define IR_ENTER             0xD3
#define IR_HOME              0x86
#define IR_BACK              0x79
#define IR_MANU              0x4A
#define IR_PLUS              0xE0
#define IR_REDUCE            0xF1
/* Global Variable ------------------------------------------------------------------------*/
extern QueueHandle_t IRRxHandle;
/* Global Fuction ------------------------------------------------------------------------*/
void IR_Init(void);
#endif   //_IR_MI_H


/* Includes -------------------------------------------------------------------------------*/
#include "ir_mi.h"
/* Private variables ----------------------------------------------------------------------*/
static uint8_t  ir_state_flag = IR_STATE_IDLE;        //接收状态记录
static uint8_t  ir_data_count = 0;        //接收数据计数
static uint32_t ir_data = 0;                //记录接收数据值
static uint32_t tim_value = 0;                //脉冲宽度测量值记录

/*Global variable -------------------------------------------------------------------------*/
QueueHandle_t IRRxHandle;        //接收数据接收队列只传递最后四位脉冲对应值

/* Private Fuctions -----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------
@brief  复位红外接收标志位与定时器
*------------------------------------------------------------------------------------*/
static void ir_reset_flag(void)
{
        ir_state_flag   = IR_STATE_IDLE;
        ir_data_count   = 0;
        ir_data = 0;
        TIM_Cmd(TIM2, DISABLE);
        TIM_SetCounter(TIM2,0);
}


/* Global Fuctions ------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------
@brief  红外端口与计时时钟初始化
*------------------------------------------------------------------------------------*/
void IR_Init(void)                              
{
        EXTI_InitTypeDef   EXTI_InitStructure;
        GPIO_InitTypeDef   GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
        /*创建队列存储红外信息*/
        IRRxHandle = xQueueCreate( 32, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
       
        /* Enable GPIOD clock */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
        /* Enable SYSCFG clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
        /* Configure PD3 pin as input floating */
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_Init(GPIOD, &GPIO_InitStructure);
       
        /* Connect EXTI Line3 to PD3 pin */
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource3);
        /* Configure EXTI Line0 */
        EXTI_InitStructure.EXTI_Line = EXTI_Line3;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;  
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);                                       
        TIM_TimeBaseStructure.TIM_Period=5000;                                                 //ARR的值
        TIM_TimeBaseStructure.TIM_Prescaler=60-1;                                        //采样分频
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;        //向上计数模式
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        TIM_ARRPreloadConfig(TIM2, DISABLE);                                                    //禁止ARR装载
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                                                 
}

/*-----------------------------------------------------------------------------------
@brief  红外接收引脚电平中断
*------------------------------------------------------------------------------------*/
void EXTI3_IRQHandler(void)
{
        if(EXTI_GetITStatus(EXTI_Line3) != RESET)
        {
                tim_value = TIM_GetCounter(TIM2);
                TIM_SetCounter(TIM2,0);
               
                if(!GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_3))            
                {//下降沿触发状态处理                       
                        if(ir_state_flag == IR_STATE_IDLE)
                        {//空闲状态 - 开始接受起始帧
                                TIM_Cmd(TIM2, ENABLE);                //使能定时器
                                ir_state_flag = IR_STATE_LEAD_ON;
                        }
                        else if(ir_state_flag == IR_STATE_LEAD_OFF)
                        {//起始帧高电平结束 - 判断高电平时间进入数据接收
                                if((tim_value>= (IR_LEAD_H - IR_MEAS_ACCURACY))&&(tim_value<= (IR_LEAD_H + IR_MEAS_ACCURACY)))
                                {
                                        ir_state_flag = IR_STATE_DATA_IDLE;
                                }
                                else
                                {
                                        ir_reset_flag();
                                }
                        }
                        else if(ir_state_flag == IR_STATE_DATA)
                        {//数据帧高电平结束-判断高电平时间区分并记录数据
                                ir_state_flag = IR_STATE_DATA_IDLE;
                                if((tim_value>= (IR_DATA_FOURTEEN_H - IR_MEAS_ACCURACY))&&(tim_value<=(IR_DATA_FOURTEEN_H + IR_MEAS_ACCURACY)))
                                {
                                        ir_data <<= 2;
                                        ir_data += IR_FOURTEEN_VALUE;
                                        ir_data_count++;
                                }
                                else if((tim_value>= (IR_DATA_ELEVEN_H - IR_MEAS_ACCURACY))&&(tim_value<=(IR_DATA_ELEVEN_H + IR_MEAS_ACCURACY)))
                                {
                                        ir_data <<= 2;
                                        ir_data += IR_ELEVEN_VALUE;
                                        ir_data_count++;
                                }
                                else if((tim_value>= (IR_DATA_EIGHT_H - IR_MEAS_ACCURACY))&&(tim_value<=(IR_DATA_EIGHT_H + IR_MEAS_ACCURACY)))
                                {
                                        ir_data <<= 2;
                                        ir_data += IR_EIGHT_VALUE;
                                        ir_data_count++;
                                }
                                else if((tim_value>= (IR_DATA_FIVE_H - IR_MEAS_ACCURACY))&&(tim_value<=(IR_DATA_FIVE_H + IR_MEAS_ACCURACY)))
                                {
                                        ir_data <<= 2;
                                        ir_data += IR_FIVE_VALUE;
                                        ir_data_count++;
                                }
                                else
                                {
                                        ir_reset_flag();
                                }
                        }
                        else
                        {//其他错误状态复位标志位
                                ir_reset_flag();
                        }                                       
                }
                else
                {//上升沿状态触发
                        if(ir_state_flag == IR_STATE_LEAD_ON)
                        {//起始帧低电平结束 - 判断电平长度进入起始帧高电平测量
                                if((tim_value>= (IR_LEAD_L - IR_MEAS_ACCURACY))&&(tim_value<= (IR_LEAD_L + IR_MEAS_ACCURACY)))
                                {
                                        ir_state_flag = IR_STATE_LEAD_OFF;
                                }
                                else
                                {
                                        ir_reset_flag();
                                }
                        }
                        else if(ir_state_flag == IR_STATE_DATA_IDLE)
                        {//数据帧低电平结束 - 判断电平长度进入数据帧高电平测量
                         //或结束帧低电平结束 - 判断电平长度等待定时器超时完成接收
                                if((tim_value>= (IR_DATA_IDLE_L - IR_MEAS_ACCURACY))&&(tim_value<= (IR_DATA_IDLE_L + IR_MEAS_ACCURACY)))
                                {
                                        if(ir_data_count < IR_DATA_LENGTH)
                                        {//数据接收未完成继续接受数据
                                                ir_state_flag = IR_STATE_DATA;
                                        }
                                        else
                                        {//数据接收完成等待定时器超时
                                                ir_state_flag = IR_STATE_END;
                                        }
                                }
                                else
                                {
                                        ir_reset_flag();
                                }
                        }
                        else
                        {//其他错误状态复位标志位
                                ir_reset_flag();
                        }
                }       
        }

        EXTI_ClearITPendingBit(EXTI_Line3);
}

/*-----------------------------------------------------------------------------------
@brief  红外接收10ms定时器溢出中断
*------------------------------------------------------------------------------------*/
void TIM2_IRQHandler(void)//计时使用每10MS中断
{
        uint8_t tmp = 0;
        portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
        {
                TIM_Cmd(TIM2, DISABLE);
                if(ir_state_flag == IR_STATE_END)
                {//结束接收状态判断并发送数据
                        /*前六个数据脉冲数据帧的符合用户数据位或者OFF前六帧则为有效数据否则抛弃*/
                        if(((ir_data>>8) == IR_CUSTOM_DATA) ||((ir_data>>8) == IR_CUSTOM_OFF))
                        {
                                tmp = (uint8_t)ir_data;
                                xQueueSendFromISR( IRRxHandle, &tmp, &xHigherPriorityTaskWoken );
                        }
                }
                else
                {
                        ir_reset_flag();
                }
                TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        }
        portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );

}

/* -------------------------------------------END OF FILE-----------------------------------------------*/
[/mw_shl_code]


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。