【蓝桥杯-嵌入式 STM32】PWM输入捕获,获取频率占空比

singlechip

本次实验使用的是蓝桥杯嵌入式大赛的指定开发板,STM32G431R8T6。

下面为 CubeMX 和代码部分

CubeMX

选择对应引脚,配置为定时器模式,设置通道一路为“Input Captu direct mode”(输入捕获直接模式用于读取周期)、一路为“Input Captu inindirect mode”(输入捕获间接模式用于计算占空比)。

预分频(PSC)设置为(时钟频率-1)以便于计算。

自动重装初值默认不变。

通道一设置为“Rising Edge”上升沿捕获、通道二设置为“Falling Edge”下降沿捕获。

生成代码。

pwm.c

#include "pwm.h"

/* 用于输入捕获 */
uint32_t tim2_val1, tim2_val2, tim3_val1, tim3_val2;	/* 保存两路通道读取的值 */
uint32_t tim2_freq, tim3_freq;												/* 保存两路PWM的频率 */
float tim2_duty, tim3_duty;														/* 保存两路PWM的占空比*/

/* PWM捕获,占空比频率	(定时器输入捕获回调函数)
 * 参数:定时器
 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)	
	{
		/* 捕获到上升沿 */
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			tim2_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);	/* 读取通道一,上升沿的值 一个完整的周期 */
			tim2_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);	/* 读取通道二,下降沿的值 一个周期中的高电平 */
			__HAL_TIM_SetCounter(htim, 0);						/* 清零定时器中的值,继续读取下一周期的脉冲 */
			
			/* 捕获到的频率 = 时钟频率 / 预分频值 / 捕获的值(从0开始直到上升沿产生读的数值) */
			tim2_freq = (80000000 / 80) / tim2_val1;
			/* 捕获的占空比 = 高电平的时间 / 低电平的时间 * 100 */
			tim2_duty = ((float)tim2_val2 / tim2_val1) * 100;
			HAL_TIM_IC_Start(htim, TIM_CHANNEL_1);
			HAL_TIM_IC_Start(htim, TIM_CHANNEL_1);
		}
	}
	else if(htim->Instance == TIM3)
	{
		/* 捕获到上升沿 */
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
		{
			tim3_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);	/* 读取通道一,上升沿的值 一个完整的周期 */
			tim3_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);	/* 读取通道二,下降沿的值 一个周期中的高电平 */
			__HAL_TIM_SetCounter(htim, 0);						/* 清零定时器中的值,继续读取下一周期的脉冲 */
			
			/* 捕获到的频率 = 时钟频率 / 预分频值 / 捕获的值(从0开始直到上升沿产生读的数值) */
			tim3_freq = (80000000 / 80) / tim3_val1;
			/* 捕获的占空比 = 高电平的时间 / 低电平的时间 * 100 */
			tim3_duty = ((float)tim3_val2 / tim3_val1) * 100;
			HAL_TIM_IC_Start(htim, TIM_CHANNEL_1);
			HAL_TIM_IC_Start(htim, TIM_CHANNEL_1);
		}
	}
	
}

pwm.h

#ifndef __PWM_H_
#define __PWM_H_

#include "main.h"

/* 用于输入捕获 */
extern uint32_t tim2_val1, tim2_val2, tim3_val1, tim3_val2;		/* 保存两路通道读取的值 */
extern uint32_t tim2_freq, tim3_freq;													/* 保存两路PWM的频率 */
extern float tim2_duty, tim3_duty;														/* 保存两路PWM的占空比*/

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);

#endif

主函数功能验证部分

sprintf(lcd_string, "R39 freq %d      ",tim3_freq);
		LCD_DisplayStringLine(Line1, (unsigned char *)lcd_string);
		sprintf(lcd_string, "R39 duty %.3f    ",tim3_duty);
		LCD_DisplayStringLine(Line2, (unsigned char *)lcd_string);
		
		sprintf(lcd_string, "R40 freq %d      ",tim2_freq);
		LCD_DisplayStringLine(Line3, (unsigned char *)lcd_string);
		sprintf(lcd_string, "R40 duty %.3f    ",tim2_duty);
		LCD_DisplayStringLine(Line4, (unsigned char *)lcd_string);

注意在 main 函数开始时,我们还需要使能 PWM输入捕获中断使能:

	/* 开启定时器2,3输入捕获中断 */
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);

演示教程视频

【B 站链接 —— 备战 2025 蓝桥杯 —— 嵌入式】PWM输入捕获

相关文章

【蓝桥杯-嵌入式 STM32】ADC、DAC

本次实验使用的是蓝桥杯嵌入式大赛的指定开发板,STM32G431R8T6。 下面为 CubeMX 和代码部分 CubeMX ADC部分 设置引脚选择ADC模式,对应通道选择“Single-ended”(单端输出)。其他默认即可 DAC部分 DAC选择“仅与外部引脚相连”。 生成代码 ad.c ``` #include "ad.h" /* ADC读取函数 * 参数 A...

singlechip

PWM输出——频率占空比可调【STM32】

本次实验使用的是蓝桥杯嵌入式大赛的指定开发板,STM32G431R8T6。 下面为 CubeMX 和代码部分 CubeMX定时器配置部分 选择对应引脚的通道设置为PWM输出模式(不要选择CH\*N)。 以获取一个100Hz,占空比为50的脉冲信号,现在设置时钟频率为80MHz,参数设置中PSC,ARR需要我们自己配置(当然我们后期实现代码修改频率、占空比的时候会修改这些数据)。 公...

singlechip

按键判断单击、双击、长按【STM32】

本次实验使用的是蓝桥杯嵌入式大赛的指定开发板,STM32G431R8T6。 下面为CubeMX和代码部分 CubeMX配置 将按键引脚设置为双边沿中断触发模式,并设置上拉电阻。 定时器本次选择TIM3,选择内部时钟源,设置PSC为80-1,COUNTER Period为1000-1,实现1ms定时(频率为80MHz) 并打开定时器中断。 Key.c ``` #inc...

singlechip