预装载、重复计数器和捕获滤波都在改变定时器事件发生的条件。调试时要把计数时钟、PWM 周期、更新事件和CPU中断分开看,才能解释“波形正确但回调频率不同”或“写了参数却还没生效”。
本页以 STM32H743、RM0433 的 TIM1/8 高级定时器及 TIM2/5 通用定时器为范围。H743 的 TIM2/5 是32位,TIM1/8等为16位;这张能力表不能套到F103。具体实例是否有RCR、互补输出或Break还需查该实例章节。
一个统一的时基例子
跳转到“一个统一的时基例子”先假定已经确认定时器内核时钟为240 MHz。设置PSC=239后:
向上、边沿对齐计数,ARR=999,CNT每1000个tick回到0,周期为1 ms。PWM1、CCR=500、高有效时得到50%的有效占空比。GPIO复用、CCxE、高级定时器MOE以及极性/空闲状态配置仍决定引脚能否输出预期波形。
240 MHz是这个例子的输入条件;H743的TIMPRE、APB分频、器件修订和电压档必须单独确认。CPU运行480 MHz不能直接推出TIM内核480 MHz,见 STM32时钟树。
PSC、ARPE 和 CCR 预装载
跳转到“PSC、ARPE 和 CCR 预装载”PSC写入的是缓冲的分频重装值。ARR是否缓冲由ARPE控制,CCR输出比较值是否缓冲由OCxPE控制。
| 设置 | 写入后何时影响正在运行的计数/比较 |
|---|---|
| PSC | 经更新装载进入实际预分频器 |
| ARPE=0 | ARR直接作用于有效值;运行中修改可能影响当前周期 |
| ARPE=1 | 写入ARR预装载,在更新事件转入有效值 |
| OCxPE=0 | 写CCR直接影响有效比较值 |
| OCxPE=1 | 写CCR预装载,在更新事件转入有效值 |
运行中把未预装载的ARR降到当前CNT以下,可能使当前周期超出预期,不能假设写入就自动把CNT复位。周期和占空比需要一起改变时,应考虑它们在哪一次更新一起生效,避免出现过渡脉冲。RM0433:定时器时基与预装载
EGR.UG可以产生更新装载,同时还涉及计数器/预分频器重新初始化和标志行为。UDIS抑制更新事件,URS选择哪些来源形成更新请求;它们不能笼统解释成“是否允许计数”。以初始化为目的使用UG后,应按当前设置清理不需要的UIF,再启用中断和输出。
RCR 与真正的更新事件
跳转到“RCR 与真正的更新事件”RCR保存重复计数器的重装值N。硬件内部维护递减计数,软件读RCR并不会看到一个每次溢出都减一的“剩余次数”。在正常周期边界触发的情形下,经过N+1次对应的边界事件才形成一次更新事件。
沿用向上计数、1 MHz、ARR=999的例子:
| RCR | 计数器溢出频率 | 正常周期边界形成的UEV频率 |
|---|---|---|
| 0 | 1000 Hz | 1000 Hz |
| 1 | 1000 Hz | 500 Hz |
| 2 | 1000 Hz | 约333.333 Hz |
PWM仍每1 ms完成一个周期;RCR=2不把PWM频率改成333 Hz。它改变更新/预装载传送及相关请求的节奏。软件UG或从模式控制器产生更新时还有另外的行为,不应把所有UEV都算成“数够三次溢出”。RM0433 第38.3.3节
H7的TIM15/16/17也有重复计数器,不能写成“只有TIM1和TIM8有RCR”。不同实例、不同系列的RCR位宽也可能不同。
中心对齐有两个边界
跳转到“中心对齐有两个边界”中心对齐计数从0上数到ARR附近再下数到0。完整周期包含 个计数tick(ARR>0),溢出和下溢都能递减内部重复计数器。
因此1 MHz、ARR=999的中心对齐PWM完整周期为1998 µs,约500.5005 Hz;RCR=2对应每三个边界才更新,并不是每三个完整PWM周期才更新。RCR初值何时写入、计数器何时启动,还会影响首次更新落在上边界还是下边界。CMS同时影响输出比较标志在哪个方向产生,应与UIF更新事件分别检查。
捕获滤波器不使用 PSC 后的时钟
跳转到“捕获滤波器不使用 PSC 后的时钟”输入捕获滤波器对输入进行采样,要求连续若干次采到一致状态才确认跳变。滤波器采样时钟由ICxF编码以及内部时钟/CKD产生的 决定,不能直接拿1 MHz的CNT时钟计算。
RM0433中两个常用编码是:
| ICxF | 采样时钟 | 连续样本数N |
|---|---|---|
| 0 | 不使用该数字滤波流程,按手册规定的输入同步路径处理 | — |
| 3 | 8 | |
| 8 | 6 |
若CK_INT为240 MHz且CKD不分频,编码3的8样本尺度约33.3 ns;编码8的6样本尺度约200 ns。这里描述的是采样窗口尺度,实际确认延迟还包含输入到采样时刻的相位和同步路径。把CKD改为分频后,使用DTS的条目也相应变化。
滤波越强,能够通过的最短高/低电平宽度和最高边沿速率就越受限制;两个通道若延迟不同还会影响相位测量。应先测信号和毛刺,再选择编码,不能无条件推荐“设置为8”。
编码器与输入捕获的不同用途
跳转到“编码器与输入捕获的不同用途”编码器模式让计数器随A/B相位关系递增或递减,适合相对位置及速度;输入捕获则在边沿到来时保存时间戳,适合周期、脉宽和相位。
“A相超前就正向”取决于A/B接线、通道映射和输入极性;接反两相会改变方向。计数器也不会自动提供绝对机械位置,通常还需要索引Z、回零或其他参考。计算速度时明确每转是单相周期数还是四倍频后的计数,并限定快照间位移不越过有符号模差的半范围。具体换算见 转速与编码器测量。
用两个捕获通道测相位
跳转到“用两个捕获通道测相位”设参考A的两个连续同类边沿为 、,同一周期内B的对应边沿为 。定义B在A之后的偏移:
例如1 MHz时基下,A起点1000、B边沿4500、下一A边沿21000,周期为20000tick,B相对A延后3500tick,得到63°。如果要表达“B领先A”,应另行声明带符号角度或归一化约定,不能在不同图中随意互换。
以下纯计算函数检查B确实位于所给A周期内。无符号差值支持32位计数器跨回绕;真实时间跨度须小于半范围,且三条时间戳已经正确配对。
#include <stdbool.h>#include <stdint.h>
bool phase_lag_degrees(uint32_t a0, uint32_t a1, uint32_t b, double *degrees){ if (degrees == 0) { return false; } uint32_t period = a1 - a0; uint32_t offset = b - a0; if (period == 0u || period >= UINT32_C(0x80000000) || offset >= period) { return false; } *degrees = 360.0 * (double)offset / (double)period; return true;}读取两个“最新CCR”不保证它们属于同一周期。如果同一次IRQ里两个捕获标志都挂起,HAL按通道检查的顺序也不等于边沿真实到达的顺序。可靠的数据收集过程应:
- 读取各通道捕获值与过捕获状态,记录所用边沿类型。
- 在约定的短时间范围内按时间戳顺序处理事件,或保留足够的捕获缓冲。
- 用两次连续A边沿建立周期,再寻找该区间内唯一符合条件的B边沿。
- 没有B、出现多个B或CCxOF时输出无效状态并重新同步。
H743 TIM2 的捕获时基配置片段
跳转到“H743 TIM2 的捕获时基配置片段”下面只初始化TIM2内核;GPIO的正确复用、封装引脚、输入电平和之后的IRQ/DMA收集由应用负责。函数会复位TIM2,要求该实例没有其他使用者。给定240 MHz输入时,PSC为239、CNT为1 MHz。
#include <stdbool.h>#include <stdint.h>#include "stm32h743xx.h"
bool tim2_capture_timebase_init(uint32_t timer_hz){ if (timer_hz < 1000000u || timer_hz % 1000000u != 0u) { return false; } uint32_t divider = timer_hz / 1000000u; if (divider > 65536u) { return false; } RCC->APB1LENR |= RCC_APB1LENR_TIM2EN; (void)RCC->APB1LENR; RCC->APB1LRSTR |= RCC_APB1LRSTR_TIM2RST; RCC->APB1LRSTR &= ~RCC_APB1LRSTR_TIM2RST;
TIM2->CR1 = TIM_CR1_URS; TIM2->PSC = divider - 1u; TIM2->ARR = UINT32_MAX; TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0 | (3u << TIM_CCMR1_IC1F_Pos) | (3u << TIM_CCMR1_IC2F_Pos); TIM2->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E; TIM2->EGR = TIM_EGR_UG; TIM2->SR = 0u; /* stopped initialization; no events to retain yet */ TIM2->CR1 |= TIM_CR1_CEN; return true;}两个通道都使用Direct TI、上升沿、捕获预分频DIV1和滤波编码3。这里没有开启中断,也没有完成三时间戳的配对状态机;不能把初始化成功当作“相位已经测得”。1 MHz的32位计数器约71.58分钟回绕,仍需使用模差并满足实际跨度条件。
Break、MOE 与互补输出
跳转到“Break、MOE 与互补输出”高级定时器的Break可按配置使MOE关闭,从硬件路径改变输出。它解决的是输出级控制,不能仅据此说“电机会立即停止”:机械惯性、续流路径、驱动器使能和输出空闲状态都影响实际结果。
应一起检查:
- Break输入的有效极性、滤波和允许来源。
- MOE、AOE及故障消失后的自动/软件重新使能策略。
- OSSI、OSSR、CR2中的OISx/OISxN、CCxP/CCxNP以及CHx/CHxN实际映射。
- 外部栅极驱动的输入定义、使能脚和故障反馈。
不能只写一行“MOE=0”就宣称某个半桥输出已经满足所有停止条件。互补输出也不是把两个普通GPIO设成相反电平;它依赖高级定时器的互补和死区单元。
死区由 tDTS 与 DTG 决定
跳转到“死区由 tDTS 与 DTG 决定”死区基于 ,不是PSC之后1 MHz计数器的1 µs。对RM0433所述DTG编码,用无符号整数 表示:
这里的 & 表示整数按位与。若 MHz,DTG=120对应约500 ns;DTG=128对应约533.3 ns;DTG=192对应约1066.7 ns。高编码区间的步长会变大,不能用一个线性倍数贯穿0~255。
选择死区要结合器件开关时间、驱动传播差、负载和实际波形。配置值还可能受LOCK保护限制,修改后应按实际输出测量;计算出寄存器值不等于已经验证功率级行为。
调试时按事件顺序观察
跳转到“调试时按事件顺序观察”先确认计数时钟和CNT变化,再看ARR/CCR何时装载、UIF与CCxIF何时出现,最后检查NVIC和回调。观察捕获必须同时记录CCxOF;观察互补PWM应同时测CHx、CHxN及Break动作。把软件中断频率当成PWM频率,或只读单个CCR判断整条测量链,都会漏掉关键条件。
需要完整寄存器和HAL字段对照时,参见 F1定时器PWM与寄存器;其中的跨系列说明同样适用,但具体能力仍以H743手册为准。