目录
基于stm32的红外遥控器捕获实验HAL库编程(美的)
本文目标:基于stm32的红外遥控器捕获实验HAL库编程(美的)
按照本文的描述,应该可以跑通实验并举一反三。
先决条件:装有编译和集成的开发环境,比如:Keil uVision5、STM32CubeMX
使用外设:USART1、GPIO、TIM2
前言
遥控器随处可见,是我们日常生活中常用的一种电子设备。它可以通过红外信号来控制电视、空调等家用电器的开关、模式、音量等功能。但是,你有没有想过,这些红外信号是如何被发送和接收的呢?本文将介绍如何使用 STM32 单片机和 HAL 库来实现一个红外遥控器的捕获实验,让你了解红外遥控的原理和编程方法。
实验目的
基于stm32的红外遥控器捕获实验HAL库编程(美的),使用码值学习模式,也就是红外接收模块接收相应的码值,通过stm32这款mcu对码值进行捕获,并通过串口打印出来。
关于美的空调红外遥控器协议R05D
美的空调红外遥控器采用R05D格式,载波频率为38KHZ。
数据格式:引导码+48位数据+分隔码+48位数据(LAA’BB’CC’ S LAA’BB’CC’)
L为引导码;
ABC为实际数据,A’为A的反码,B’为B的反码,C’为C的反码;
S为分隔码;
第二帧数据和第一帧一样;
L引导码:4.5ms低电平+4.5ms高电平(以解析方分析,编码方刚好相反,下面不再概述)
数据0格式
550us低+550us高就识别成数据0
数据1格式
550us低+1600us高就识别成数据0
分隔码
完整时序图
关于实验原理图
本次工程的目标是识别出相应的数据,目标了解,开工。
搭建工程
使用STM32CubeMX配置stm32的基本配置。基本的配置如下:开启swd调试,开启外部时钟。
- 配置USART1,用于printf调试
-
配置time3
-
时钟界面选项卡:
- 工程选项卡:
点击右上角的的生成代码:
使用keil打开工程,编译工程,一切都是ok
编写代码实现需求
我们的目标是使用定时器的定时效果。
开始编写代码,首先要把串口的打印映射好,使用下面的代码片段可用正常使用printf打印
int fputc( int ch, FILE *f )
{
USART_TypeDef* USARTx = USART1;
while ((USARTx->SR & (1<<7)) == 0);
USARTx->DR = ch;
return ch;
}
接下来创建两个文件mytime.c和mytime.h写一些代码。其中mytime.c的代码如下:
#include "mytime.h"
#include <stdio.h>
#include "tim.h"
// 定义全局变量
unsigned char g_ir[IR_RECEVIE]; // 存储脉冲宽度的数组
unsigned int g_ir_n; // 存储脉冲个数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// 使用定时器 3 的通道 2 来测量一个红外信号的脉冲宽度,并将结果存储在一个数组g_ir 中
if(htim->Instance == htim3.Instance)
{
if(g_ir_n<IR_RECEVIE)
if(HAL_TIM_ACTIVE_CHANNEL_2 == htim3.Channel)
{
if(g_ir_n%2) // 如果是偶数个脉冲(下降沿)
{
g_ir[g_ir_n] = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_2);
TIM3->CNT = 0; // 将定时器的计数值清零
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING); // 将定时器的捕获极性设置为下降沿
g_ir_n++; // 将脉冲个数加一
}
else // 如果是奇数个脉冲(上升沿)
{
if(g_ir_n) // 如果不是第一个脉冲(第一个脉冲为引导码的上升沿,不需要记录)
{
g_ir[g_ir_n] = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_2);
TIM3->CNT = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
g_ir_n++;
}
else // 如果是第一个脉冲(引导码的上升沿)
{
TIM3->CNT = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
g_ir_n++;
}
}
}
}
}
// 定时器回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
}
}
error: #53: expected a “:”
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
解决报错问题,根据对应的报错信息,期望得到一个;一直跳过去看源码,把相应的错误处理掉
去工程目录,把stm32f1xx_hal_tim.h的只读属性去掉,就可以进行更改了,是hal库一个bug,不知道后期相应的固件版本解决了没,我这里是手工处理一些。
mytime.h的内容如下:
#ifndef __MYTIME_H__
#define __MYTIME_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#define IR_RECEVIE 600
extern unsigned int g_ir_n; // 存储脉冲个数
extern unsigned char g_ir[IR_RECEVIE];
#ifdef __cplusplus
}
#endif
#endif /*__ __MYTIME_H__ */
在main函数中简单进行测试一下
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
for(int i = 1; i <= g_ir_n; i++)
{
printf("0x%02x\n",g_ir[i]);
}
printf("%d\r\n",g_ir_n);
// 清一下数组
for(int i = 1; i <= g_ir_n; i++)
{
g_ir[i] = 0;
}
g_ir_n = 0;
HAL_Delay(1000); //延时 1000 毫秒,避免占用过多 CPU 资源
}
main.c中的编写的代码片段
接下来简单的对工程配置一下
烧入代码,观察实验现象。
实验现象
这里当按下对应的遥控器按键时,串口会打印出一串码值,关于这段码值的解析,我单独使用表格的方式进行解析了,也就是只看高位识别,比如图片中0xa3,最高位是1,所以解析成1,0x34,最高位是0,所以解析成0。解析的数据符合抓取的波形,符合目标对应的数据格式:引导码+48位数据+分隔码+48位数据(LAA’BB’CC’ S LAA’BB’CC’),所以本次实验成功。
本文中使用的测试工程
https://download.csdn.net/download/weixin_44317448/88294428?spm=1001.2014.3001.5501