摘要TIM 触发 DMA 搬运 ADC 数据示波器看 ADC 在采样但 DMA 缓冲区数据错位不是 DMA 配置错了而是 TIM 的Update Event 与TRGO 信号没对齐。本文解析 TIM 触发 DMA 的“隐形条件”。一、问题描述现象**TIM 配置 1kHz 触发 ADCDMA 配置 Circular 模式搬运运行一段时间后ADC 数据在缓冲区里错位、重复或丢失。**很多工程师的排查方向是DMA Burst 长度不对内存地址没对齐ADC 采样时间太短二、原理分析1. 物理模型TIM 触发 DMA 的信号链TIM Counter - Update Event (UEV) - TRGO (Trigger Output) - DMA Request - DMA Transfer2. 核心参数UEV (Update Event)计数器溢出/下溢时产生的事件。TRGO (Trigger Output)TIM 输出给其他外设的信号。DMA RequestDMA 控制器接收到的请求源。3. 反直觉真相“Update Interrupt Enable” 不等于 “DMA Trigger”。你开启了TIM_IT_UPDATE只能进中断。你没配置TRGO UpdateDMA 永远收不到触发信号。结果DMA 靠“猜”或者靠“相邻通道的副作用”在跑迟早错位。三、工程级解决方案方案 1明确配置 TRGO最关键必须显式指定 TIM 的触发输出。// STM32 HAL 示例 htim1.Init.RepetitionCounter 0; HAL_TIM_Base_Init(htim1); // 关键选择 Update 作为 TRGO __HAL_TIM_SET_TRGO(htim1, TIM_TRGO_UPDATE);方案 2DMA 与 TIM 的同步点DMA 传输发生在UEV 之后不是 CNT0 的瞬间。正确时序CNT 计数到 ARR。产生 UEV。触发 DMA。DMA 读取 ADC-DR。错误理解认为 DMA 在 CNT0 时触发 → 采样窗口未结束数据未稳定。方案 3防止“鬼触发”如果使用 TIM 的One Pulse ModeDMA 只会触发一次。必须手动重启 TIM或改用 Continuous 模式。四、选型避坑建议TRGO 源的选择TIM_TRGO_UPDATE最常用适合周期性采样。TIM_TRGO_OC1适合相位可控的触发。DMA Stream 优先级TIM 触发的 DMA 建议设为Very High防止被 SPI/UART 抢占导致错位。双缓冲Double Buffer高频采样 100kHz强烈建议开启 DMA 双缓冲。五、总结 Checklist[ ] 是否配置了TIM_TRGO_UPDATE[ ] DMA 请求是否映射到了正确的 TIM 触发源[ ] 是否在 Circular 模式下验证了长时间运行的稳定性[ ] ADC 采样时间是否足够在 TIM 周期内完成六、写在最后关注我少走弯路我是 gqqsherry一个拒绝调包、专注底层逻辑的嵌入式工程师。TIM DMA ADC 是嵌入式里“铁三角”级别的联动任何一个环节没对齐数据就全乱。关注我的专栏《嵌入式底层避坑指南》下一篇我们将深入解析《编码器模式转得乱七八糟别只怪电机看看 TI1/TI2 极性》。下一篇预告《编码器计数忽多忽少别只怪码盘看看 TIM 的输入滤波与极性》原创文章转载请注明出处。
DMA + TIM 触发异常?别只怪时钟,看看 Update 与 TRGO
摘要TIM 触发 DMA 搬运 ADC 数据示波器看 ADC 在采样但 DMA 缓冲区数据错位不是 DMA 配置错了而是 TIM 的Update Event 与TRGO 信号没对齐。本文解析 TIM 触发 DMA 的“隐形条件”。一、问题描述现象**TIM 配置 1kHz 触发 ADCDMA 配置 Circular 模式搬运运行一段时间后ADC 数据在缓冲区里错位、重复或丢失。**很多工程师的排查方向是DMA Burst 长度不对内存地址没对齐ADC 采样时间太短二、原理分析1. 物理模型TIM 触发 DMA 的信号链TIM Counter - Update Event (UEV) - TRGO (Trigger Output) - DMA Request - DMA Transfer2. 核心参数UEV (Update Event)计数器溢出/下溢时产生的事件。TRGO (Trigger Output)TIM 输出给其他外设的信号。DMA RequestDMA 控制器接收到的请求源。3. 反直觉真相“Update Interrupt Enable” 不等于 “DMA Trigger”。你开启了TIM_IT_UPDATE只能进中断。你没配置TRGO UpdateDMA 永远收不到触发信号。结果DMA 靠“猜”或者靠“相邻通道的副作用”在跑迟早错位。三、工程级解决方案方案 1明确配置 TRGO最关键必须显式指定 TIM 的触发输出。// STM32 HAL 示例 htim1.Init.RepetitionCounter 0; HAL_TIM_Base_Init(htim1); // 关键选择 Update 作为 TRGO __HAL_TIM_SET_TRGO(htim1, TIM_TRGO_UPDATE);方案 2DMA 与 TIM 的同步点DMA 传输发生在UEV 之后不是 CNT0 的瞬间。正确时序CNT 计数到 ARR。产生 UEV。触发 DMA。DMA 读取 ADC-DR。错误理解认为 DMA 在 CNT0 时触发 → 采样窗口未结束数据未稳定。方案 3防止“鬼触发”如果使用 TIM 的One Pulse ModeDMA 只会触发一次。必须手动重启 TIM或改用 Continuous 模式。四、选型避坑建议TRGO 源的选择TIM_TRGO_UPDATE最常用适合周期性采样。TIM_TRGO_OC1适合相位可控的触发。DMA Stream 优先级TIM 触发的 DMA 建议设为Very High防止被 SPI/UART 抢占导致错位。双缓冲Double Buffer高频采样 100kHz强烈建议开启 DMA 双缓冲。五、总结 Checklist[ ] 是否配置了TIM_TRGO_UPDATE[ ] DMA 请求是否映射到了正确的 TIM 触发源[ ] 是否在 Circular 模式下验证了长时间运行的稳定性[ ] ADC 采样时间是否足够在 TIM 周期内完成六、写在最后关注我少走弯路我是 gqqsherry一个拒绝调包、专注底层逻辑的嵌入式工程师。TIM DMA ADC 是嵌入式里“铁三角”级别的联动任何一个环节没对齐数据就全乱。关注我的专栏《嵌入式底层避坑指南》下一篇我们将深入解析《编码器模式转得乱七八糟别只怪电机看看 TI1/TI2 极性》。下一篇预告《编码器计数忽多忽少别只怪码盘看看 TIM 的输入滤波与极性》原创文章转载请注明出处。