本文主要内容是STM32的定时器输入捕获,基于MDK_ARM,STM32 CUBEMX,keil软件和STM32F407VGT6最小系统板,实现PWM的输出与捕获,并通过串口输出捕获信息。
在RCC设置HSE为晶振
配置时钟树,我在这里设置使得APB总线时钟频率为84MHz
将TIM2 通道1的模式选为输入捕获
选择TIM2时钟源为内部时钟源
预分频系数设为APB总线频率减一 我这里设置为84-1
预装载值设为最大
开启预装载
开启TIM中断
这里选择TIM3的通道1生成PWM,占空比,脉宽,周期可以自由设置
在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捕获
和单通道捕获的设置相似,我这里选择的是TIM2_CH1 和TIM2_CH2为输入捕获,TIM3_CH1和TIM4_CH1为PWM输出
因为增加了一路捕获,自定义结构体声明也相应增加。我这里在末尾加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 */