You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 TIM1中心对齐模式3下更新事件仅在ARR触发的求助

STM32 TIM1中心对齐模式3下仅在ARR触发更新事件的解决方案

针对TIM1中心对齐模式3下更新事件在ARR和0处均触发的问题,本质是该模式下硬件默认会在计数器向上溢出(到达ARR)和向下下溢(到达0)时都产生更新事件(UEV)。要实现仅在ARR处触发ADC采样,可通过以下三种方案解决:


方案1:改用CC事件/TRGO硬件触发ADC(推荐纯硬件实现)

放弃使用更新事件触发ADC,改用计数器到达ARR时的捕获/compare(CC)事件作为触发源,完全通过硬件配置实现需求:

  1. 配置空闲CC通道:选择一个未用于PWM输出的TIM1通道(如CC3/CC4),将其CCR值设为ARR,配置为定时模式(仅触发事件,不输出PWM)。
  2. 设置TRGO触发源:将TIM1的TRGO输出绑定为该CC事件,再配置ADC以TIM1_TRGO为触发源。

HAL库代码示例

// 配置TIM1的CC3通道,CCR3 = ARR值
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = TIM1->ARR; // 绑定CCR值到ARR
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);

// 配置TRGO输出为CC3事件
TIM_MasterConfigTypeDef sMasterConfig = {0};
sMasterConfig.MasterOutputTrigger = TIM_TRGO_CC3;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);

// 配置ADC触发源为TIM1_TRGO
ADC_HandleTypeDef hadc1;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
HAL_ADC_Init(&hadc1);

方案2:软件过滤更新事件(适合允许少量软件干预场景)

保留更新事件触发ADC,但在DMA/中断回调中通过计数方向判断,仅处理ARR处的触发:

  1. 读取TIM1_CR1寄存器的DIR位:DIR=0表示向上计数到ARR触发的更新,DIR=1表示向下计数到0触发的更新。
  2. 仅在DIR=0时处理ADC采样数据,忽略DIR=1的触发。

代码示例(DMA完成回调)

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
    if (hadc->Instance == ADC1) {
        // 判断TIM1当前计数方向
        if (!(__HAL_TIM_GET_COUNTERMODE(&htim1) == TIM_COUNTERMODE_DOWN)) {
            // 仅处理向上计数到ARR时的采样数据
            process_adc_data(adc_buffer);
        }
        // 重新启动ADC DMA循环采样
        HAL_ADC_Start_DMA(&hadc1, adc_buffer, BUFFER_SIZE);
    }
}

方案3:模拟中心对齐模式(软件控制计数方向)

放弃硬件中心对齐模式,改用向上/向下计数模式手动切换,仅在ARR处触发更新事件:

  1. 初始配置TIM1为向上计数模式,开启更新中断。
  2. 当计数器到达ARR触发中断时,切换为向下计数模式;当计数器到达0时,再切换回向上计数模式。此时更新事件仅在ARR处产生。

HAL库代码示例

// 初始配置为向上计数模式
TIM_Base_InitTypeDef sTimBaseInit = {0};
sTimBaseInit.Prescaler = YOUR_PRESCALER;
sTimBaseInit.CounterMode = TIM_COUNTERMODE_UP;
sTimBaseInit.Period = YOUR_ARR_VALUE;
sTimBaseInit.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim1);

// 开启TIM更新中断
HAL_TIM_Base_Start_IT(&htim1);

// 更新中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM1) {
        if (__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) {
            // 向下计数到0,切换为向上计数
            __HAL_TIM_SET_COUNTERMODE(htim, TIM_COUNTERMODE_UP);
            __HAL_TIM_SET_COUNTER(htim, 0);
        } else {
            // 向上计数到ARR,切换为向下计数并触发ADC采样
            __HAL_TIM_SET_COUNTERMODE(htim, TIM_COUNTERMODE_DOWN);
            HAL_ADC_Start_DMA(&hadc1, adc_buffer, BUFFER_SIZE);
        }
    }
}

注意事项

  • 方案1中需确保所选CC通道未被PWM占用,若所有通道都在使用,可考虑复用通道的事件触发功能(不影响PWM输出)。
  • 方案3需保证中断响应及时,避免计数方向切换延迟影响PWM输出精度。

内容的提问来源于stack exchange,提问作者Electrone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:08:21