文章目录
- 前言
- 一、单通道捕获
-
- 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新建项目
文章图片
选择STM32型号,我这里用的是STM32F407VGT6
文章图片
(2)时钟配置 在RCC设置HSE为晶振
文章图片
配置时钟树,我在这里设置使得APB总线时钟频率为84MHz
文章图片
(3)定时器捕获配置 将TIM2 通道1的模式选为输入捕获
文章图片
选择TIM2时钟源为内部时钟源
文章图片
预分频系数设为APB总线频率减一 我这里设置为84-1
文章图片
预装载值设为最大
文章图片
开启预装载
文章图片
开启TIM中断
文章图片
文章图片
(4)定时器PWM配置 这里选择TIM3的通道1生成PWM,占空比,脉宽,周期可以自由设置
文章图片
(5)串口配置 选用串口,我这里选的是串口1
文章图片
(6)设置代码生成相关 【笔记|使用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输出
文章图片
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 */
文章图片
回调函数也相应增加
/* 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 */
最后编译运行
文章图片
通过串口调试助手可以看到捕获的两路PWM信息
推荐阅读
- #|【蓝桥杯嵌入式】【STM32】13_PWM输入捕获模式
- 笔记|Mybatis---ResultMap自定义映射规则
- 计算机网络|计算机网络---物理层实验
- 笔记|TransGAN代码复现—九天毕昇平台
- 笔记|JAVA中的练习
- 操作系统|回顾2016年(我们见证了一场存储行业的厮杀)
- Python实现QQ音乐爬取下载最新可用
- 蓝桥杯|蓝桥杯单片机最全备考资料(真题、代码、原理图、指导手册、资源包)
- 蓝桥杯|蓝桥杯单片机省赛国赛资料(2020年前的检索)