基于STM32F1-HAL库的红外接收程序

更新时间:2024-03-09 16:39:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于STM32F1 HAL库的红外解码程序,核心思想是通过外部下降沿中断记录相邻两个下降沿的时间,记录的数据存入数组,再根据数据判断是0还是1,获得NEC协议的4个码。程序使用PG15作为中断输入,使用基本定时器7定时,相比在中断里面等待的方式节省了CPU时间,提高了效率,也方便移植到其他型号的MCU上。程序没有处理连发的问题,感兴趣的可以尝试修改。 .c文件

#include \

//irdata[33]存储相邻下降沿的cnt计数值 uint8_t irdata[33],cnt = 0,IR_OK=0;

TIM_HandleTypeDefir_timx;

void IR_Init(void) {

GPIO_InitTypeDefGPIO_InitStruct; IR_GPIO_CLK_ENABLE;

GPIO_InitStruct.Pin = IR_GPIO_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; //下降沿中断 GPIO_InitStruct.Pull = GPIO_PULLUP; //上拉 HAL_GPIO_Init(IR_GPIO_PORT, &GPIO_InitStruct);

}

HAL_NVIC_SetPriority(IR_EXTI_IRQn,1,1); HAL_NVIC_EnableIRQ(IR_EXTI_IRQn); IR_TIMx_Init(249,71);

//Tout = (arr+1)*(psc+1)/sck

//设计Tout = 250us,psc = 71,arr = 249,sck = 72MHz void IR_TIMx_Init(uint16_t arr,uint16_t psc) {

ir_timx.Instance = IR_TIMx;

ir_timx.Init.Prescaler = psc;

ir_timx.Init.CounterMode = TIM_COUNTERMODE_UP; ir_timx.Init.Period = arr;

ir_timx.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

ir_timx.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

IR_TIMx_RCC_CLK_ENABLE();

HAL_NVIC_SetPriority(IR_TIMx_IRQn, 1, 0); HAL_NVIC_EnableIRQ(IR_TIMx_IRQn);

HAL_TIM_Base_Init(&ir_timx);

}

__HAL_TIM_CLEAR_FLAG(&ir_timx,TIM_FLAG_UPDATE); HAL_TIM_Base_Start_IT(&ir_timx);

//定时器中断服务函数

void IR_TIMx_IRQHandler(void) {

HAL_TIM_IRQHandler(&ir_timx); }

//定时器更新中断回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { }

//外部中断服务函数

//根据霖锋老师89C51篇关于红外接收的程序修改 void IR_EXTI_IRQHandler(void) {

if(htim->Instance == IR_TIMx) { }

cnt++;

static uint8_t uCounter;

static uint8_t Startflag = 0;//开始接收标志

HAL_GPIO_EXTI_IRQHandler(IR_GPIO_PIN); if(!Startflag) { Startflag = 1; cnt = 0;

}

else if(Startflag) { if((cnt<60)&&(cnt>40))

uCounter = 0; irdata[uCounter] = cnt; cnt = 0; uCounter++;

if(uCounter == 33) { uCounter = 0; IR_OK = 1; Startflag = 0;

}

}

//引导码检测 (9+4.5)/0.25 = 54 //cnt存储了相邻两个下降沿的时间差 //接收完成 }

//获得命令码

//成功返回命令码,错误返回0 uint8_t IR_GET_CODE(void) {

uint8_t i,j,k = 1,value = 0,ir_code[4]; //ir_code[0]:用户码 ir_code[1]:用户码反码

ir_code[2]:命令码 ir_code[3]:命令码反码 9>6

}

value|=0x80; k++;

if(IR_OK !=1)

return 0;

else {

IR_OK = 0; for(i=0;i<4;i++) {

for(j=0;j<8;j++) {

value >>=1; //注释部分对应低位在前的情况 if(irdata[k]>6)

//0:1.125/0.25 = 4.5<6 ,1:2.25/0.125 =

}

}

}

ir_code[i] = value;

k = 1; value = 0;

if(ir_code[2] + ir_code[3] == 0xFF) //数据校验 { } else

return 0;

return ir_code[2];

//返回的是命令码

.h文件

#ifndef _BSP_IR_H #define _BSP_IR_H

#include \

//用PG15的EXTI中断来检测红外引脚电平跳变,基本定时器7用来计时 //可根据自己需要修改

#define IR_TIMx TIM7

#define IR_TIMx_RCC_CLK_ENABLE() __HAL_RCC_TIM7_CLK_ENABLE()

#define IR_TIMx_IRQn TIM7_IRQn #define IR_TIMx_IRQHandler TIM7_IRQHandler

#define IR_GPIO_CLK_ENABLE __HAL_RCC_GPIOG_CLK_ENABLE() #define IR_GPIO_PORT GPIOG #define IR_GPIO_PIN GPIO_PIN_15

#define IR_EXTI_IRQn EXTI15_10_IRQn #define IR_EXTI_IRQHandler EXTI15_10_IRQHandler //遥控器上按键的控制码,十进制,根据自己遥控器上的按键修改 #define POWER 162 #define MODE 98

#define SPEAK 226 #define PLAY 34 #define PREV 2

#define NEXT 194 #define EQ 224 #define VOL_PLUS 144

#define VOL_REDU 168 #define RPT 152 #define U_SD 176 #define ZERO 104

#define ONE 48 #define TWO 24

#define THREE 122 #define FOUR 16 #define FIVE 56 #define SIX 90

#define SEVEN 66 #define EIGHT 74 #define NINE 82

void IR_Init(void);

void IR_TIMx_Init(uint16_t arr,uint16_t psc); uint8_t IR_GET_CODE(void);

#endif

Main函数中直接调用IR_GET_CODE函数即可获得命令码。

本文来源:https://www.bwwdw.com/article/12ua.html

Top