STM32CubeMX定时器配置
STM32CubeMX定时器配置
- 一,Mode界面
- 1,Slave Mode (从模式)
- 2,Trigger Source (触发源)
- 三,Channelx(通道模式)
- 1,Input Capture
- 2,Output Compare
- 3,PWM Generation
- 4,Forced Output
- 5,DEPRECATED → Input Capture Indirect mode 的那条灰字?
- 6,初学者落地套路
- 二,Configuration
- Parameter Settings
- 1,Counter Settings:
- 2,Trigger Output(TRGO)Parameters
一,Mode界面
在下面这张图中,你看到的是STM32CubeMX中的TIM3定时器的Mode配置界面。让我逐个解释各个配置选项:
1,Slave Mode (从模式)
有以下选项:
何为定时器的从模式?
就是定时器依赖于外部的触发信号来启动计数或者响应事件
如果将从模式设置为Disable:即关闭从模式,定时器依据系统时钟(默认的内部时钟)独立运行,不依赖外部触发信号
应用场景:10 kHz PWM、1 ms 定时中断
如果设置为External Clock Mode 1 (外部时钟模式 1):定时器将外部时钟作为计数源
电路连接:外部待测方波 → ETR 或 TIx
应用场景:① 频率计数 ② 霍尔测速(电机转速)
怎么频率计数?
我们把待测信号(方波)接到 TIM3 的 ETR(或 CH1/CH2),把 TIM3 当成“脉冲计数器”,另一颗定时器(比如 SysTick 或 TIM2)给 1 s 门控,在 1 s 里读 TIM3->CNT 寄存器的计数值,就得到“这 1 秒来了多少个脉冲”。
怎么实现霍尔测速?
无刷电机霍尔传感器每转产生若干脉冲 → 接 TIM3 ETR引脚,把 TIM3 设成 External Clock Mode 1,PSC=0,每来 1 个霍尔沿,CNT 就 +1,然后我们固定一段时间读取CNT,或利用另一定时器 100 ms 中断读取,就能算出转速 (pulses/100 ms)。
如果设置为Reset Mode (复位模式):外部脉冲一到,CNT 立即清零
定时器检测到外部触发信号时,重新从0计数(使用默认的内部时钟计数)
硬件连接:外部脉冲 → 连接到ETR/TIx
应用场景:① 周期测量(Period)② 相位差测量(Phase)
如何测量周期?
将信号(每周期一个脉冲,例如霍尔 Index、编码器 Z 相)→连接到 ETR,定时器使用默认的内部时钟 1 MHz,每收一次 Z 相脉冲,CNT 清零,到下一个脉冲时: CNT 的值 = 周期的微秒数。
如何测量相位差?
假设测量两路方波 A、B的、相位差:A连接→主定时器产生 TRGO,B连接→从定时器 ETR。当 B 脉冲来时复位计数器,再用主定时器给的时间基准读取 CNT,就得到 A→B 的相位差。
如果设置为Gated Mode (门控模式):高电平才计数,低电平就暂停
外部触发信号控制定时器计算的开始与停止(定时器还是使用内部时钟进行计数)
硬件连接:待测信号→ 连接 TIM3 ETR。
应用场景:① 脉宽测量(High-level Width),② 占空比测量
如何测量脉宽?
把待测 PWM 的高电平当“门”,连接到ETR。当ETR检测到高电平时,CNT开始计数(在另外一个输入捕获通道记录这个上升沿对应的 CNT1),当电平跳变到低电平时CNT停止计数,等到下一次上升沿到来时CNT再开始计数(在另外一个输入捕获通道记录这个上升沿对应的 CNT2),一个周期内高电平持续的微秒数 = CNT2 - CNT1(假设内部时钟频率是1MHz)
如果设置为Trigger Mode (触发模式):定时器检测到外部触发信号时,重新启动(计数器不清0)
硬件连接:主定时器的 TRGO → 连接从定时器的 ITRx
应用场景:① 多定时器同步起跑,② One-Shot 采样窗口
如何实现两个定时器同时计数?
把 TIM1 设置成主定时器 Master,更新事件 (UEV) 输出到 TRGO,把 TIM3 设置为触发模式:SMCR.SMS=Trigger Mode,TS=ITR0(ITR0=来自 TIM1 的 TRGO),这样的效果是:上电后 TIM3 直到收到 TIM1 的第一次更新事件才开始计数,于是两路 PWM 同步
如何实现一次( One-Shot )采样?
比如我们需要:ADC 需要在某个外部事件后 5 µs 打开采样窗口,ADC只采样一次
我们把 TIM2 作主定时器,事件来时产生 TRGO,TIM3 设置为从定时器: Trigger Mode,ARR=5 µs,对应“5 µs 后产生更新中断”,在中断里触发 ADC,完成一次采样
相信大家都有疑问:上面Reset Mode (复位模式)和Trigger Mode (触发模式)的应用举例中都提到了主定时器和从定时器,以及主定时器会产生TRGO(触发输出信号)传递给从定时器的ITRx引脚(片内引脚,不占IO),明明我们只设置了Reset Mode (复位模式)和Trigger Mode (触发模式),哪来的TRGO?哪来的主定时器和从定时器呢?
其实主定时器这这里的作用只是相当于产生一个触发信号TRGO,通过ITRx(如ITR0)传递给从定时器,在CubeMX中的Slave Mode可以设置从定时器接收到TRGO的反应:
Reset Mode : CNT 立即清零,再继续计数
Trigger Mode :第一沿到来:启动 CNT;后续到来:再次“重启”一个周期
Gated Mode :只要 ITR0 为高,CNT 计数;低则暂停
External Clock 1 Mode :直接把 ITR0 的边沿当时钟脉冲,CNT 每沿+1
TRGO的本质是主定时器用自己的“更新事件 (UEV)”或“比较事件 (OCxREF)”等,做成一次脉冲,通过寄存器 CR2.
MMS
送出,同时芯片手册会给出一张表:将定时器与TRx线对应,比如TIM1 TRGO→ ITR0,TIM2 TRGO→ ITR1,这样从定时器就可以选择 ITR0/1/2/3 当触发源Trigger Source (TS
)了,然后从定时器就可以根据Slave Mode(SMS
)做不同动作。
那怎么在CubeMX中设置主定时器和从定时器呢?
在Mode配置区下的Configurtion选项可以配置
下面以TIM1为主定时器,TIM3为从定时器举例:
主定时器TIM1 (Master):
Master/Slave Mode: Enable
Trigger Output (MMS): 选 Update Event(或者 OC1REF 等)
从定时器TIM3 (Slave):
Clock Source: Internal Clock(CNT 还是内部时钟)
Trigger Source (TS): ITR0 (因手册注明 TIM1→ITR0)
Slave Mode (SMS):
测周期 ➜ Reset Mode
多路 PWM 同步 ➜ Trigger Mode
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; // 或 TIM_SLAVEMODE_TRIGGER
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig);
┌──────── TIM1 ────────┐│ Update Event (UEV) ││ OC1REF pulse … │──► TRGO (TIM1)└─────────────────-────┘│片内触发矩阵│(ITR0)▼┌──────── TIM3 (Slave) ───────┐│ TS=ITR0 SMS=Reset ││ ││ 触发来 → CNT=0 │└─────────────────────────────┘
专有名词 | 含义 | 物理 / 逻辑通道 | 你在 CubeMX 里看到的字段 |
---|---|---|---|
TRGO | Timer Request Generate Output,定时器的“触发输出信号” | 由 主 定时器内部产生,经内部总线送到别的定时器 | Trigger Output (Master Mode) |
ITR0‥ITR3 | “内部触发输入线”,把上面某个定时器的 TRGO 接进来 | 片内线,不占 IO | Trigger Source (TS) 里选 ITR0/1/2/3 |
ETR | External Trigger pin,真正的芯片脚 | 需要占用一个 GPIO/AF | 也在 Trigger Source 下拉框里 |
Slave-Mode Controller | 定时器内部的小状态机 | 决定收到触发后干什么(Reset / Gated / Trigger …) | Slave Mode (SMS) |
2,Trigger Source (触发源)
前面Slave Mode (从模式)讲的是定时器依赖外部触发信号产生的行为:
Reset Mode : CNT 立即清零,再继续计数
Trigger Mode :第一沿到来:启动 CNT;后续到来:再次“重启”一个周期
Gated Mode :只要 ITR0 为高,CNT 计数;低则暂停
External Clock 1 Mode :直接把 ITR0 的边沿当时钟脉冲,CNT 每沿+1
而产生这些行为是需要触发源的,这就是接下来我们要讲的Trigger Source (触发源):
我们暂且将这些触发源分为两大类:
1,内部触发源:触发信号来自定时器内部引脚(不是IO),如ITR0 / ITR1 / ITR2 / ITR3
这一类上面讲过,再举例一下:
ITRx | 对应哪路 TRGO (以常见 STM32F4 为例^1) | 举例 |
---|---|---|
ITR0 | TIM1_TRGO | TIM1 主控 PWM,对齐 TIM3/TIM4 |
ITR1 | TIM2_TRGO | 用 TIM2 周期触发 TIM5 复位 |
ITR2 | TIM3_TRGO | 用 TIM3 事件门控 TIM1 |
ITR3 | TIM4_TRGO | 多定时器级联计数 |
2,外部触发源:触发信号来自外部引脚(定时器的IO引脚),如ETRx、TI1_ED、TI1FP1、TI2FP2
我们先来讲讲ETRx怎么使用?
-
配合 External Clock Mode 1 :实现外部时钟的输入
如下图,Clock Source选项可以选择内部时钟和外部时钟(ETR2引脚输入外部时钟)
-
配合 门控 / 复位 / 触发 , SMS 选 Gated/Reset/Trigger:前面Slave Mode (从模式)提到过一些应用场景,比如测量外部信号频率,周期,测霍尔转速
那TI1_ED、TI1FP1、TI2FP2 怎么使用呢?
首先我们发现这三个触发源都含有TI1,这是什么意思呢?我们应该知道定时器的引脚叫CHx,比如CH1,而CH1 是“通道 1”——它既能当 输出(PWM、比较脉冲),也能当 输入(捕获外部信号):
当它被用作输入时,这条连线在手册里就叫 TI1(Timer Input 1)
当它配置成 输出 → 我们习惯说 CH1、CC1、OC1
那哪里来的TI1_ED、TI1FP1、TI2FP2 呢?
其实就是TI1的输入分支:
TI1 pin ──┬─► TI1_ED (Edge 脉冲)
├─► TI1FP1 (Filtered Level)
└─► CAPTURE/COMPARE 正常用的 CH1
-
TI1_ED 就是 TI1 Edge Detector 翻译过来就是边沿检测器,专门用来捕捉输入边沿(上升沿/下降沿),让 Reset/Trigger Mode 在那一刻生效
应用举例:把 1 MHz 方波接 TI1,Slave Mode 选 External Clock Mode 1 → CNT 就是一台 1 MHz 计数器。 -
TI1FP1 就是 TI1 Filtered Pulse 1:此通道会将高电平进行滤波,适合测量静态(不变的)电平持续时间
应用举例:
门控计时:想测 PWM 的高电平宽度 → 把 PWM 接 TI1,Trigger Source 选 TI1FP1,Slave Mode 选 Gated。计数器只在 PWM 高电平那段时间累加,读取 CNT 就是“高电平持续多少微秒”。
有噪声的外部复位:长线过来的 5 V 脉冲可能抖动,滤波后再当 Reset Mode 触发,就不会被毛刺误复位 -
TI1FP1和TI2FP2搭配起来的用法:测量A相和B相相位差
B 相 ─► CH2 (TI2) ─► TI2FP2 ─►〔Slave-Mode: Reset〕–──┐
A 相 ─► CH1 (TI1) ─► Input-Capture ─► CCR1 ◄── CNT ──┘
_______________________ ▲
Internal clock (1 MHz 等)
上面将B相连接到TI2FP2作为触发源,模式为Reset,当B波到来时,CNT被清0,
而A相连接到TI1FP1作为触发源,并且启用 Input Capture (输入捕获):检测上升沿时,硬件会在那个上升沿瞬间 把CNT的值抄一份存进CCRx
—— 这动作叫“捕获”
我们打开 CC1 Capture interrupt中断,当捕获到上升沿会进入回调,在回调里读CCR1
,使用函数HAL_TIM_ReadCapturedValue(&htim, TIM_CHANNEL_1)读取,流程图如下:
__ CNT: …152 153 154 155 …
_________________ ↑
外部上升沿──────┘ │ ← 这时硬件把 154 放进CCR1
__________________ └─CCR1
= 154
此时使用函数读取的CCR1的值就是154,再结合预分频就能得到真实时间
上面提到了CCR1,它是干什么的呢?
其全称是Capture / Compare Register 1即捕获/比较寄存器1,它里面存的是什么呢?
输出模式下:存储要比较或生成 PWM 的阈值
输入捕获模式下:存储硬件抄的 CNT 值
上面还提到将CH1设置为 Input Capture,将CH2设置为Slave-Mode: Reset,这两个模式有什么联系呢?
首先我们要明确:Input Capture ➜ 属于“通道功能”;Slave Mode ➜ 控制“计数器行为”。示意图如下:
如上所示
Channel 里(CH1, CH2…):
你可以选 PWM、Output Compare、或 Input Capture,可以设置通道作用(选 Input Capture 时,和 CCMRx、CCR1/2
等寄存器打交道)
Slave Mode 区块:
完全独立的一个小状态机,只关心 “触发源来了我要不要清 CNT / 门控 CNT / 把外部沿当时钟”,(配置在 SMCR 寄存器)
其实将CH2选择为TI2FP2,设置为Slave-Mode: Reset是不够的,同时也要将CH2设置为Input-Capture模式,为什么?
因为只有当 CH2 处于 输入模式 时,硬件才能把这根脚送进滤波器(TI2FP2通道之前要滤波),再生成 TI2FP2 这条支路供 Slave-Mode 控制器使用,也就是说TI2FP2 并不是“独立存在”的,但在CubeMX配置时:如下图,我们只设置Slave Mode和TI1FP1,之后,CH1就自动配置为 Input Capture 了,下图发现,Channel1只能 Input Capture 或者Disable
如果我们将Trigger Sourcs配置为TI2FP2,此时就轮到CH2只能 Input Capture 或者Disable了
把触发源与从模式搭配起来举例:
需求(小白版说法) | 该选哪条 Trigger Source | 该选哪个 Slave Mode |
---|---|---|
“有几个沿,就加几个数”(计脉冲、做频率计) | TI1_ED 或 TI2FP2 | External Clock Mode 1 |
“沿一来就把表清零”(测周期/相位) | TI1_ED / TI2FP2 / ITRx / ETR | Reset |
“门打开期间才计数”(测高电平时间、占空比) | TI1FP1 / TI2FP2 | Gated |
“外部枪响大家一起跑”(多定时器对齐) | TI1_ED / ITRx | Trigger |
动手步骤示例:测 PWM 高电平宽度
硬件:把待测 PWM 信号插到定时器 CH1 引脚。
CubeMX:
Trigger Source → TI1FP1
Slave Mode → Gated Mode
Clock Source → Internal Clock(给 CNT 一个已知计数频率)
运行:读一次 CNT 就是“这次 PWM 高电平持续多少计数”;除以时钟频率得到时间(µs)
三,Channelx(通道模式)
下图展示了通道功能选项:
1,Input Capture
首先看到Input Capture又分为三个模式:
1,Direct mode (直连模式)
2,Indirect mode (间接模式)
3,Triggered by TRC
Direct mode这种输入模式就是前面选择触发源(外部)时使用的模式
Triggered by TRC这种输入模式就是前面选择触发源(内部)时使用的模式
上图中Triggered by TRC是灰色的,相信如果前面看懂的话就知道:这个通道输入模式是主定时器产生的TRGO信号到从定时器的ITR引脚,我们没有打开ITR:
所以这种输入模式不能选择
在这里为了加深理解,我继续深入讲解前面测量AB相相位差的例子:
前面我们知道,B相接通道CH2,触发源为TI2FP2,从模式设置为Reset,而A相连接通道CH1,触发源为TI1FP1,并且Channel1设置为Input Capture Direct mode (CubeMX 会在初始化后调用HAL_TIM_IC_Start()或 HAL_TIM_IC_Start_IT(),把捕获使能位 CCER.CC1E = 1,此位会把 CNT 锁存进 CCR1),重点是CH2的Channel2设置为失能(把捕获使能位 CCER.CC1E = 0,不会把 CNT 锁存进 CCR1)
CC1E 只是“是否把 CNT 写进 CCR1” 的闸门。
带不带它 都不影响 TI2FP2 这根线被当作触发源去控制计数器CNT。
选项 | 硬件连线 | 细节 | 常见用途 |
---|---|---|---|
Direct mode | 输入到GPIO的信号→TI1 | 沿直接触发捕获 | 测方波周期、测 PWM 占空比(配另一通道) |
Indirect mode (灰掉说明芯片不支持) | TI2 捕获 CCR1 或反之 | 让 CH1 捕获来自 CH2 的信号 | 双线编码器特殊玩法,较少用 |
Triggered by TRC | 片内 TRC (触发控制器) | 用别的 TIM 的 TRGO 触发捕获 | 多定时器同步测量 |
2,Output Compare
选项 | 会不会往外翻电平 | 你能做什么 | 典型用法 |
---|---|---|---|
No Output | ❌ 不占 GPIO | 仅在 CNT == CCR1 时产生 OC1 中断 或 DMA 事件 | 软件定时 (精确 µs 级延时)、发逻辑脉冲给别的外设 |
CH1 | ✅ | OC 模式可设 Toggle / Active / Inactive / PWM-Mode1/2 | 在 IO 上翻转一次、产生方波 |
CH1N | ✅(互补脚) | 需高级 TIM | 半桥驱动下,由硬件自动生成反相信号 |
CH1 CH1N | 两脚同开 | 同时输出主/互补 | 三相电机 FOC 中常见 |
3,PWM Generation
选项 | 输出在哪 | 说明 |
---|---|---|
PWM Generation No Output | ❌ | 只有计数+更新中断,不占脚——适合纯软件读取“斜坡”或作触发用 |
PWM Generation CH1 | CH1 | 最常用:CCR1=占空比、ARR=周期 |
PWM Generation CH1N | CH1N | 高级 TIM 才有;互补输出带死区 |
PWM Generation CH1 CH1N | CH1+CH1N | 同步互补对 |
在 中心对齐 (Center-Aligned) 或 边沿对齐 (Edge-Aligned) 由 计数模式 决定。
死区、刹车、互补极性在 BDTR/CCER 寄存器设置,CubeMX 也有图形化选项。
4,Forced Output
用途
上电让 MOSFET 全关、让继电器保持常开;
发生故障时,软件/硬件一口气把 PWM 脱离计数器立即输出固定电平。
区别于 GPIO 输出
仍然走定时器通道,可与死区、刹车逻辑兼容,不用重新改 GPIO 复用状态。
在 CubeMX
选 Forced Output CH1 → 还需在 “配置” 页面里选 Force High 或 Force Low。
5,DEPRECATED → Input Capture Indirect mode 的那条灰字?
一些老款 MCU 支持 “Indirect” 捕获,但新架构已不推荐;CubeMX 直接灰掉提示 Deprecated。
如果你确实需要此功能,只能手写寄存器(CCMRx.CC1S = 10 等)。
6,初学者落地套路
目标 | Channel 下拉要选 | 其他关键点 |
---|---|---|
测某信号频率 | Input Capture direct | 捕获上升沿,读 CCR;或当触发源计脉冲 |
输出固定 1 kHz 50% PWM | PWM Generation CHx | PSC+ARR 定周期,CCR = ARR/2 |
产生一次 10 µs 脉冲 | Output Compare CHx | OC 模式选 Toggle;中断里快速改 CCER 关闭 |
上电先拉低、启动后变 PWM | 上电先 Forced Output Low → 软件再改成 PWM Generation |
二,Configuration
Parameter Settings
我们可以看到在Parameter Settings下面又有Counter Settings和Trigger Output(TRGO)Parameters两个大类:
1,Counter Settings:
1,Prescaler (PSC):定时器的预分频系数
在讲预分频系数之前,我觉得有必要补充一些定时器的基础知识:
我们知道时间是抽象的,我们人类具象化时间的方式就是利用周期性的事件,比如地球自转一圈为1天,秒针布进一格为1秒,单片机时钟源的一个脉冲(可以理解为方波)就是一个时间单位。
而定时器的本质就是脉冲计数器,它对时钟源发出的脉冲进行计数,而这个脉冲的频率除了时钟源的影响,我们还可以使用分频器Prescaler 改变
在CubeMX中打开时钟树可以看到,我们设置系统时钟是180MHz,经过APB1总线分频器(除以4)后,得到45MHz的频率,这个频率给APB1总线的外设,也会经过2倍频为90MHz输送到定时器,而定时器自己也有预分频器就是Prescaler
上面我们知道进入定时器的频率为90MHz,我一般会将Prescaler 与 APB1 Timer clocks保持一致(这里是90分频),因为这样实际到达定时器的频率就是1MHz,(频率M是106倒数对应周期u即10-6),1MHz刚好是1us产生一个脉冲,CNT加1
那为什么下面设置的不是90 ,而是90-1呢?
因为分频机制是:分频后的频率 = 分频前的频率 / (Prescaler + 1),这里已经加1了,为了凑出90,我们要提前减1
2,Counter Period (ARR)自动重装载值:
在讲Counter Period (ARR)之前,我们继续补充定时器的知识:当计数器(CNT)数到自动重装载值(ARR)发生“溢出(Update)”动作而清0,并触发更新中断(Update Interrupt,简称 “UIF”)
注意:溢出和更新是有区别的,溢出(Overflow)是CNT到达它的极限值(ARR)然后翻转到初始值的动作本身,而更新(Update Event,简称 Update)是指CNT清0的那一刻会产生一个事件,这个事件(+中断使能位 DIER.UIE=1)会触发定时器更新中断
所以ARR就是决定CNT上限的一个值,可以控制定时器产生更新事件(如果中断使能位 DIER.UIE=1,ARR就可以控制更新中断的周期)
接下来请思考:我想让定时器每过100ms就产生一个更新事件(进入定时器的时钟频率按上面的90MHz,预分频系数按上面的90-1),怎么时钟ARR的值?
根据上面所学,CNT+1表示1us,我让CNT最大为100 000(即ARR = 100 000),就是100ms产生一个更新事件了
其实这里ARR应该为99 999,因为ARR = 0时也算一个CNT)
3,Count Mode计数模式:
Up 模式(向上计数):从 0 一直加到 ARR,然后再从头(重新)从 0 开始。
Down 模式(向下计数):直接从 ARR 开始往下数到 0,然后从 0 下一步再跳回 ARR 继续往下数。
Center-aligned 模式(对称中心对齐,也叫三角波模式):“先从 0 往上数到 ARR,再从 ARR 往下数回 0,然后再向上……不断重复”。
4,auto-reload preload (ARPE):
打开“双缓冲”,防止你改 ARR 时立刻跳变
5,Internal Clock Division (CKD):
再次细分时钟,主要给数字滤波用
2,Trigger Output(TRGO)Parameters
我前面提到过就是设置主定时器的
1, Trigger Event Selection (MMS):
我们先来回顾:什么是 TRGO(触发输出)
TRGO(Trigger Output)可以理解成:
当定时器“做完某件事”时,它会在芯片内部发出一个“触发脉冲”,这个脉冲可以供其他定时器或**外设(如 ADC、DMA)**去接着用。
在 CubeMX 里,这个“做完某件事”由 Trigger Event Selection (MMS) 决定,例如:
Update Event(每次溢出/更新) → 只要 CNT 数到 ARR,就发一个脉冲出去;
OC1REF(通道 1 比较/PWM 的比较输出到达)→ 只要 PWM 达到某个阈值,就发脉冲。
一旦选好了 “哪件事送到 TRGO”,其它从定时器在它的 Trigger Source(ITRx)里就可以选对应的那条内部线(ITR0/ITR1/…),实现级联、联动。
2,Master/Slave Mode (MSM):
在三个定时器连极时,第二给定时器既做主定时器又作从定时器时,为中间的定时器打开,保证时序同步