忙了一天终于用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]
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
多个中断运行,单片机也不觉得累..没毛病.
一周热门 更多>