STM32F411RE定时器计数值验证脉冲宽度及预分频器计算咨询
问题分析与解决方案
一、计数值波动大的根本原因
你当前代码的核心问题是在EXTI中断回调函数中做阻塞式while循环,这完全违背了中断服务函数的设计原则:
- 中断服务函数必须尽可能短,不能做任何阻塞操作,否则会导致系统无法响应其他中断、甚至死机
- 循环内重复读GPIO电平的方式,无法可靠捕获下降沿,还可能因为GPIO电平抖动、中断优先级冲突等导致计数错误
正确的做法是给输入引脚配置上升沿+下降沿双触发EXTI中断,分别在上升沿启动定时器并记录初始值,下降沿停止定时器并记录当前值,最后计算差值:
#include <stdint.h> volatile uint32_t timerStartValue = 0; volatile uint32_t timerEndValue = 0; volatile uint32_t timeDifference = 0; const uint32_t counterMaxValue = UINT32_MAX; // 用标准库宏更规范 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GATE1_Pin) { if(HAL_GPIO_ReadPin(GATE1_GPIO_Port, GATE1_Pin) == GPIO_PIN_SET) { // 上升沿:清零计数器并启动定时器 __HAL_TIM_SET_COUNTER(&htim2, 0); HAL_TIM_Base_Start(&htim2); timerStartValue = TIM2->CNT; } else { // 下降沿:停止定时器并计算差值 HAL_TIM_Base_Stop(&htim2); timerEndValue = TIM2->CNT; // 处理计数器溢出与正常情况的差值计算 if(timerEndValue >= timerStartValue) { timeDifference = timerEndValue - timerStartValue; } else { timeDifference = counterMaxValue - timerStartValue + timerEndValue + 1; } } } }
二、验证计数值与示波器测量值的匹配方法
要验证计数值是否准确,需先明确定时器的计数时钟周期,核心公式如下:
计数时钟频率 = APB1时钟频率 / (预分频器值 + 1) 计数周期 = 1 / 计数时钟频率 实际脉冲宽度 = timeDifference × 计数周期
以你当前配置为例:
- APB1时钟=80MHz,预分频器=39999
- 计数时钟频率=80MHz/(39999+1)=2kHz
- 计数周期=1/2kHz=0.5ms
- 示波器测量的4.16ms脉冲,对应的理论计数值=4.16ms / 0.5ms≈8(误差±1个计数周期为正常范围)
你之前得到的15764、61454等数值明显不符合,也印证了原代码逻辑的错误。
验证步骤:
- 用示波器测量准确的脉冲宽度T(比如4.16ms)
- 按公式计算理论计数值N = T / 计数周期
- 运行修正后的代码,读取
timeDifference,对比N和实际值,误差在±1个计数周期内即为正常
三、正确计算预分频器值
预分频器的选择需要平衡测量分辨率和最大测量范围,TIM2是32位定时器,最大计数值为UINT32_MAX(4294967295),计算规则如下:
计算逻辑
- 确定需要的最小分辨率(比如1us、10us、1ms)
- 根据分辨率计算计数时钟频率:
计数时钟频率 = 1 / 分辨率 - 预分频器值 = (APB1时钟频率 / 计数时钟频率) - 1
示例计算(基于80MHz APB1时钟)
需求1:1us分辨率(适合窄脉冲测量)
计数时钟频率=1MHz,预分频器=(80MHz/1MHz)-1=79
最大测量时间=4294967295×1us≈4295秒(约71分钟),完全覆盖100Hz脉冲(周期10ms)需求2:10us分辨率(适合宽脉冲测量,降低溢出概率)
计数时钟频率=100kHz,预分频器=(80MHz/100kHz)-1=799
最大测量时间=4294967295×10us≈42949秒(约12小时)需求3:1ms分辨率(适合超宽脉冲)
计数时钟频率=1kHz,预分频器=(80MHz/1kHz)-1=79999
最大测量时间=4294967295×1ms≈4295000秒(约49.7天)
注意事项
- 预分频器值必须是0~65535之间的整数(STM32预分频器为16位寄存器)
- 优先选择满足分辨率需求的最小预分频器(即最高计数时钟频率),以保证测量精度
内容的提问来源于stack exchange,提问作者Ariarikta
相关产品推荐
相关产品推荐

