【STM32Cube笔记】系列文章目录
1-基于STM32的VSCode入门级教程前言
2-STM32Cube安装教程
3-STM32CubeIDE汉化
4-STM32Cube配置时钟设置
5-跑马灯引脚配置
6-Cortex-M7内核基本配置
7-新建用于储存代码的文件夹以及c/h文件
8-STM32CubeIDE点亮跑马灯
9-STLink调试
10-异步串口收发USART
11-中断控制器NVIC
12-配置外部中断
13-使用定时器产生PWM输出
14-使用定时器捕获上升/下降沿
15-数模转换AD/DA
16-STM32Cube个性化定制
7.5 使用定时器捕获上升/下降沿
7.5.1 配置输入捕获中断引脚
点击“Timers”并选择“TIM2”-“Channel1”将定时器2的通道1选为“Input Capture dirct mode”,使其连接至开发板上的“KEY_UP”按钮。在下方的配置栏中将分频数设为480,得到1MHZ的频率,也就是1us记一次,点击“Counter Period”,再点击右边的齿轮设置,将表达形式设成Hex格式,再将“Counter Period”设置为0xffffffff,这样就支持32位的定时器输入捕获了(部分引脚达不到只能16位)。将捕获方式设为“UP”上升沿捕获,开启自动重置,并将最底下一栏滤波值改为8。
在“ NVIC Settings”中将使能中断打开。
同时进入“GPIO Settings”将该输入捕获引脚设为下拉,保证无信号时能稳定低电平。
接着我们需要再设置一个定时器去隔3秒来统计定时器2捕获到的高电平数。
将定时器4设为普通定时器来读取捕获数量,分频数为48000得到10KHZ频率,计数30000为3秒,同时开启自动重载防止溢出。同时在“NVIC Setting”中开启全局中断。
7.5.2 配置串口传输数据
接下来对串口进行配置,将“USART1”打开。并开启USART1全局中断。
同时进入“NVIC”中断时序管理页面中,将“USART1”的中断优先度取到3。
同时找到PA9和PA10将它们设置为USART1的RXD和TXD引脚,方便USB读取。
点击保存并生成代码。
7.5.3 配置定时器捕获代码
首先我们需要重新到“NVIC.h”中添加“usart.h”以及printf和定时器捕获函数的声名。
接着到“NVIC.c”文件中添加一些用于储存定时器捕获的缓存变量,并在“NVIC_Init”函数中添加定时器4的初始化用于3秒反馈一次数值。
同时添加新的“NVIC_Catch”函数用于在main函数中开启定时器中断并反馈数值。
在定时器反馈函数“HAL_TIM_PeriodElapsedCallback”中添加定时器4的反馈值,使其3秒向串口传输一次数据。
接着再添加一个输入捕获到上升沿的回调函数“HAL_TIM_IC_CaptureCallback”用于对捕获的上升沿信息进行处理并储存至缓存数组中。
最后别忘了在Main函数中添加”NVIC_Catch”。
将程序烧录 至单片机后,将USB MINI线从ST-Link拔下来并连接串口。
由于选用的定时器2通道1串联了按键至3.3V,因此在打开串口后,按“KEY_UP”按键即可手动制造一个上升沿给单片机,并在串口中显示出来。
7.5.4 定时器捕获函数介绍
__HAL_TIM_SET_CAPTUREPOLARITY不是函数,而是底层操作的一个宏定义
在stm32H7xx_hal_tim.h文件中找到。其作用是修改定时器某一通道的输入捕获极性
其中有两个函数,第一个为清除清除原来的捕获极性,第二个为设置通道捕捉极性
等价于:
TIM_RESET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1); //清除原来的捕获极性
TIM_SET_CAPTUREPOLARITY(&TIM2_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器5通道1设置为下降沿捕获(重设捕获极性)
在修改定时器某一通道的输入捕获极性时,一定要先清除该通道之前捕获极性
__HAL_TIM_GET_COMPARE也是一个宏定义。
在stm32H7xx_hal_tim.h文件中找到。其作用是获取定时器某一通道的捕获寄存器值
等价于 : HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
两者都是直接读取对应CCRx寄存器的值。附上程序源码:
#include "main.h"
#include "tim.h"
#include "gpio.h"
#include "usart.h"
#include "stdio.h"
// 重定向printf start
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
if(HAL_UART_Transmit(&huart1,ptr,len,0xffff) != HAL_OK)
{
Error_Handler();
}
}
// 重定向printf end
void NVIC_Catch(void);
void NVIC_Init(void);
#include "NVIC.h"
static int capture_Buf[3] = {0}; //存放计数值
static int capture_Cnt = 0; //状态标志位
static int high_time=0; //高电平时间
void NVIC_Init(){
HAL_TIM_Base_Start_IT(&htim1); //HAL库开启定时器1
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);//HAL库开启定时器3,并使用通道4输出PWM
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, 990);//HAL库修改占空比至99%
HAL_TIM_Base_Start_IT(&htim4); //HAL库开启定时器1
}
void NVIC_Catch(){
switch (capture_Cnt){
case 0:
capture_Cnt++;
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); //启动输入捕获 或者: __HAL_TIM_ENABLE(&htim2);
break;
case 3:
high_time = capture_Buf[1]- capture_Buf[0]; //高电平时间
capture_Cnt = 0; //清空标志位
break;
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { //中断回调函数
if (htim->Instance == htim1.Instance) { //判断是哪个定时器产生中断
HAL_GPIO_TogglePin(IO_LED0_GPIO_Port, IO_LED0_Pin); //HAL库控制IO_LED0电平反转
{
if(TIM2 == htim->Instance)
{
switch(capture_Cnt){
case 1:
capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING); //设置为下降沿捕获
capture_Cnt++;
break;
case 2:
capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止捕获 或者: __HAL_TIM_DISABLE(&htim2);
capture_Cnt++;
break;
}
}
}