笔记|使用STM32cubemx进行定时器单多路pwm输入捕获


文章目录

  • 前言
  • 一、单通道捕获
    • 1.STM32 CUBEMX 配置
    • (1) 新建STM32 CUBEMX工程
    • (2)时钟配置
    • (3)定时器捕获配置
    • (4)定时器PWM配置
    • (5)串口配置
    • (6)设置代码生成相关
    • 2.Keil配置
    • 二、多通道捕获
    • 1.STM32 CUBEMX 配置
    • 2.Keil配置

前言 本文主要内容是STM32的定时器输入捕获,基于MDK_ARM,STM32 CUBEMX,keil软件和STM32F407VGT6最小系统板,实现PWM的输出与捕获,并通过串口输出捕获信息。
一、单通道捕获 1.STM32 CUBEMX 配置 (1) 新建STM32 CUBEMX工程 选择通过MCU新建项目
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

选择STM32型号,我这里用的是STM32F407VGT6
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

(2)时钟配置 在RCC设置HSE为晶振
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

配置时钟树,我在这里设置使得APB总线时钟频率为84MHz
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

(3)定时器捕获配置 将TIM2 通道1的模式选为输入捕获
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

选择TIM2时钟源为内部时钟源
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

预分频系数设为APB总线频率减一 我这里设置为84-1
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

预装载值设为最大
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

开启预装载
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

开启TIM中断
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

(4)定时器PWM配置 这里选择TIM3的通道1生成PWM,占空比,脉宽,周期可以自由设置
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

(5)串口配置 选用串口,我这里选的是串口1
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

(6)设置代码生成相关 【笔记|使用STM32cubemx进行定时器单多路pwm输入捕获】笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

2.Keil配置 在main.c中添加代码 ,根据开头和结尾/* */定位:
自定义变量结构体声明
/* USER CODE BEGIN PV */ uint32_t capture_Buf[3]={0}; //捕获值 uint8_t capture_Cnt=0; //设置状态标志位 uint8_t overload_Cnt=0; //溢出标志 uint32_t high_time; //高电平时间 uint32_t low_time; //低电平时间 double HL_time; double LL_time; double fre; double duty; /* USER CODE END PV */

添加回调函数
/* USER CODE BEGIN PFP */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance==htim2.Instance) { switch(capture_Cnt){ case 0: 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 1: capture_Buf[1]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); //得到捕获值 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING); //设置上升沿捕获 capture_Cnt++; break; case 2: capture_Buf[2]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); //得到捕获值 HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止输入捕获 high_time=capture_Buf[1]-capture_Buf[0]+overload_Cnt*0xFFFFFFFF; //高电平时间 low_time=capture_Buf[2]-capture_Buf[1]+overload_Cnt*0xFFFFFFFF; //低电平时间 HL_time=high_time*0.001; LL_time=low_time*0.001; fre=1/(HL_time+LL_time)*1000; duty=HL_time/(HL_time+LL_time)*100; capture_Cnt=0; //清空标志位 overload_Cnt=0; //清空溢出标志位 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); break; } } } /* USER CODE END PFP */

开启PWM和捕获
/* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); //设置为下降沿捕获 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); //开启输入中断 /* USER CODE END 2 */

在usart.c中添加代码
/* USER CODE BEGIN 1 */ int fputc(int ch,FILE *f) { HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,1000); return 0; } /* USER CODE END 1 */

/* USER CODE BEGIN 0 */ #include "stdio.h" /* USER CODE END 0 */

在main.c中设置串口
/* USER CODE END WHILE */ printf("频率:%7.31fHz,%4.11f%%,高电平时间:%7.31fms,低电平时间:%7.31fms\r\n\r\n",fre,duty,HL_time,LL_time); HAL_Delay(2000); /* USER CODE BEGIN 3 */

/* USER CODE BEGIN Includes */ #include"stdio.h" /* USER CODE END Includes */

最后编译下载
二、多通道捕获 tim2 定时器有四个通道,都有输入捕获模式。可以通过设置实现单定时器多通道的PWM捕获
1.STM32 CUBEMX 配置 和单通道捕获的设置相似,我这里选择的是TIM2_CH1 和TIM2_CH2为输入捕获,TIM3_CH1和TIM4_CH1为PWM输出
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

2.Keil配置 因为增加了一路捕获,自定义结构体声明也相应增加。我这里在末尾加1来区分
/* USER CODE BEGIN PV */uint32_t capture_Buf[6]={0}; //捕获值 uint8_t capture_Cnt=0; //设置状态标志位 uint8_t overload_Cnt=0; //溢出标志 uint8_t capture_Cnt1=0; //设置状态标志位 uint8_t overload_Cnt1=0; //溢出标志 uint32_t high_time; //高电平时间 uint32_t low_time; //低电平时间 uint32_t high_time1; //高电平时间 uint32_t low_time1; //低电平时间 double HL_time; double LL_time; double HL_time1; double LL_time1; double fre; double duty; double fre1; double duty1; /* USER CODE END PV */

笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

回调函数也相应增加
/* USER CODE BEGIN PFP */void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance==htim2.Instance) { if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1) { switch(capture_Cnt){ case 0: 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 1: capture_Buf[1]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); //得到捕获值 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING); //设置上升沿捕获 capture_Cnt++; break; case 2: capture_Buf[2]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); //得到捕获值 HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止输入捕获 high_time=capture_Buf[1]-capture_Buf[0]+overload_Cnt*0xFFFFFFFF; //高电平时间 low_time=capture_Buf[2]-capture_Buf[1]+overload_Cnt*0xFFFFFFFF; //低电平时间 HL_time=high_time*0.001; LL_time=low_time*0.001; fre=1/(HL_time+LL_time)*1000; duty=HL_time/(HL_time+LL_time)*100; capture_Cnt=0; //清空标志位 overload_Cnt=0; //清空溢出标志位 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); break; } } if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2){ switch(capture_Cnt1){ case 0: capture_Buf[3]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2); //得到捕获值 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_2,TIM_ICPOLARITY_FALLING); //设置下降沿捕获 capture_Cnt1++; break; case 1: capture_Buf[4]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2); //得到捕获值 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_2,TIM_ICPOLARITY_RISING); //设置上升沿捕获 capture_Cnt1++; break; case 2: capture_Buf[5]=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2); //得到捕获值 HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_2); //停止输入捕获 high_time1=capture_Buf[4]-capture_Buf[3]+overload_Cnt1*0xFFFFFFFF; //高电平时间 low_time1=capture_Buf[5]-capture_Buf[4]+overload_Cnt1*0xFFFFFFFF; //低电平时间 HL_time1=high_time1*0.001; LL_time1=low_time1*0.001; fre1=1/(HL_time1+LL_time1)*1000; duty1=HL_time1/(HL_time1+LL_time1)*100; capture_Cnt1=0; //清空标志位 overload_Cnt1=0; //清空溢出标志位 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING); HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2); break; } } } }/* USER CODE END PFP */

其中
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)


if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)

分别表示进入TIM2_CH1和TIM2_CH2
相应地开启新加入的定时器通道
/* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); MX_TIM3_Init(); MX_USART1_UART_Init(); MX_TIM4_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); //设置为下降沿捕获 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING); //设置为下降沿捕获 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); //开启输入中断 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2); //开启输入中断/* USER CODE END 2 */

添加TIM2_CH2的printf
/* USER CODE BEGIN 3 */ printf("频率:%7.31fHz,%4.11f%%,高电平时间:%7.31fms,低电平时间:%7.31fms\r\n\r\n",fre,duty,HL_time,LL_time); HAL_Delay(2000); printf("频率1:%7.31fHz,%4.11f%%,高电平时间1:%7.31fms,低电平时间1:%7.31fms\r\n\r\n",fre1,duty1,HL_time1,LL_time1); HAL_Delay(2000); } /* USER CODE END 3 */

最后编译运行
笔记|使用STM32cubemx进行定时器单多路pwm输入捕获
文章图片

通过串口调试助手可以看到捕获的两路PWM信息

    推荐阅读