硬件前提是单片机支持定时器TRGO事件输出及主从级联,如STM32F4/F7/H7、GD32F4系列;主定时器需配置MMS=0b100输出UEV,从定时器设为外部时钟或触发模式并选择对应TRGO源,ADC须关闭软件启动且EXTSEL指向从定时器TRGO,所有时钟与参数须预先配置完成。

定时器级联触发ADC的硬件前提是什么
单片机必须支持定时器输出事件(如TRGO)作为ADC的外部触发源,且至少有两个定时器能配置为主从关系。常见满足条件的平台包括STM32F4/F7/H7系列(TIM2/TIM3可设为主,TIM8/TIM1可设为从)、GD32F4系列;而基础型如STM32F0或某些8位MCU通常不支持TRGO级联,强行配置会导致ADC_CR2_EXTEN无效或采样时序漂移。
- 主定时器需启用更新事件输出(
TIMx_CR2_MMS = 0b100),这是触发链起点 - 从定时器必须配置为“外部时钟模式1”或“触发模式”,并选择主定时器的TRGO为输入源(
TIMx_SMCR_TS = 0b101等,具体值查对应芯片参考手册) - ADC必须关闭软件启动(
ADC_CR2_EXTEN != 0),且EXTSEL字段指向从定时器的触发信号(如EXTSEL = 0b1010对应TIM3_TRGO) - 所有模块时钟必须已使能,且ADC预分频、采样周期等参数在触发前完成配置,否则首次触发可能丢失
为什么用两个定时器而不是一个定时器+ADC直接触发
单个定时器的更新事件(UEV)虽然能直接触发ADC,但无法实现「多路同步瞬时采样」所需的精细相位控制。比如需要对三相电流(IA/IB/IC)在电角度0°、120°、240°三个严格等间隔点同时采样,此时:
- 主定时器生成基准周期(如PWM载波周期),输出TRGO到从定时器
- 从定时器配置为“复位模式”,其计数器由主TRGO清零,并通过
TIMx_CCRx设置不同比较值,分别输出TRGO1/TRGO2/TRGO3到多个ADC(若芯片支持多ADC同步)或分时触发同一ADC的多个通道(需配合注入组) - 若只用一个定时器,所有ADC触发沿完全重合,无法错开采样时刻;而级联后,从定时器的比较事件可精确偏移主周期的任意整数倍
TCLK,误差仅取决于定时器时钟抖动(通常
STM32中配置TIM2→TIM3→ADC1的典型寄存器顺序
顺序错误会导致触发静默或时序紊乱,尤其注意时钟使能与寄存器写入的依赖关系:
- 先开启所有相关时钟:
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN;,RCC->AHB1ENR |= RCC_AHB1ENR_ADC1EN; - 配置主定时器TIM2:自动重装载值
TIM2->ARR = 999(1kHz基准),预分频TIM2->PSC = 83(假设84MHz APB1),然后设置TIM2->CR2 = TIM_CR2_MMS_2(MMS=100b → TRGO=UEV) - 配置从定时器TIM3:先清零
TIM3->CR1 = 0,再设TIM3->SMCR = TIM_SMCR_TS_2 | TIM_SMCR_SMS_2(TS=101b选TIM2_TRGO,SMS=010b为触发模式),最后设TIM3->ARR = 333,TIM3->CCR1 = 111(用于ADC触发点) - ADC1配置:确保
ADC1->CR2 |= ADC_CR2_EXTEN_1(上升沿触发),ADC1->CR2 &= ~ADC_CR2_EXTSEL,再置ADC1->CR2 |= (0b1010 (EXTSEL=1010 → TIM3_TRGO) - 最后统一使能:先启TIM2(
TIM2->CR1 |= TIM_CR1_CEN),再启TIM3(TIM3->CR1 |= TIM_CR1_CEN),最后启ADC(ADC1->CR2 |= ADC_CR2_ADON)
实际运行中容易忽略的同步失效点
- 主定时器未真正产生TRGO:检查
TIMx_CR2_MMS是否写入成功(有些库函数会覆盖该位),以及TIMx_EGR是否手动触发过一次更新事件(TIMx_EGR = TIM_EGR_UG)来初始化TRGO电平
- 从定时器未响应TRGO:确认
TIMx_SMCR_TS选择的触发源编号与主定时器实际输出TRGO的编号一致(例如TIM2_TRGO是TS=101b,但误配成100b就会静默)
- ADC触发延迟超预期:若使用高分辨率(如16位)或慢速时钟(如ADCCLK=14MHz),
ADC_SMPR1中通道采样时间设置过短会导致转换未完成就被下一次触发打断,表现为ADC_DR读数恒为0或随机跳变
- 多ADC同步时DMA地址未对齐:当TIM3_TRGO同时触发ADC1和ADC2,若两路DMA目标缓冲区起始地址非字对齐(如
uint16_t buf[1024]定义在栈上导致地址奇数),可能引发总线错误而非单纯采样失败
TIMx_CR2_MMS是否写入成功(有些库函数会覆盖该位),以及TIMx_EGR是否手动触发过一次更新事件(TIMx_EGR = TIM_EGR_UG)来初始化TRGO电平 TIMx_SMCR_TS选择的触发源编号与主定时器实际输出TRGO的编号一致(例如TIM2_TRGO是TS=101b,但误配成100b就会静默) ADC_SMPR1中通道采样时间设置过短会导致转换未完成就被下一次触发打断,表现为ADC_DR读数恒为0或随机跳变 uint16_t buf[1024]定义在栈上导致地址奇数),可能引发总线错误而非单纯采样失败 级联触发本身不难,难的是每个环节的时序约束都得卡准——主从定时器的时钟域切换、ADC模拟前端建立时间、DMA搬运带宽,任何一环没压住,同步就变成“看起来同步,实则各采各的”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











