ST意法半导体
直播中

李鑫

8年用户 1418经验值
私信 关注
[问答]

STM32H723使用DMA方式实现定时器输入捕获只能执行一次吗?

  目的:我们希望在 STM32H723 平台上以 DMA 模式实现定时器输入捕获,而不中断当前问题:使用 Cube MX 配置相关参数,只使用 tiM4 的 CH2 作为输入采集直接模式,Slave Mode 选择 Reset Mode,选择 TI2FP2 作为触发源,然后生成相应的代码。频率测量已经可以了,但只会测量一次,如果外部输入频率从 1000Hz 降低到 500Hz,它只能重置程序再次全速运行以再次测量 500Hz,否则它将永远是 1000Hz。不知道问题出在哪里?我怀疑触发器源可能配置不正确?或者您是否必须同时打开 CH1 和 CH2 通道,一个直接打开,一个间接打开?相关配置请参考附件希望能指导一下,非常感谢

回帖(2)

赵静

2025-3-12 09:13:38
从你的设计配置来看,感觉是想要TIMER输入功能的PWM输入模式来做测量。
这个时候我们往往将测量用的TIMER配置在复位模式,被测信号通过CH1或CH2进来,
TIMER针对被测信号的上沿和下沿分别捕获,以测量周期和占空比。
举报

风来吴山

2025-3-13 18:25:14

在使用 STM32H723 的定时器输入捕获功能时,如果通过 DMA 方式实现频率测量,且只能执行一次捕获,可能是由于配置或触发源设置不正确导致的。以下是一些可能的原因和解决方案:


1. 触发源配置



  • 你提到使用 TI2FP2 作为触发源,并且 Slave Mode 选择 Reset Mode。这种配置在理论上是可以工作的,但需要确保触发源和从模式配置正确。

  • 检查 TIM4TRGI(触发输入)是否正确配置为 TI2FP2,并且 Slave Mode 确实设置为 Reset Mode。这可以通过 TIM4->SMCR 寄存器来验证。


2. DMA 配置



  • 确保 DMA 配置为循环模式(Circular Mode),这样 DMA 可以不断地将捕获的数据传输到缓冲区中,而不是只传输一次。

  • 在 CubeMX 中,确保 DMA 通道的 Mode 设置为 Circular,并且 Data WidthMemory Address 正确配置。


3. 定时器配置



  • 确保 TIM4Capture/Compare 寄存器(CCR2)在每次捕获后能够正确更新。

  • 检查 TIM4->CCMR1 寄存器,确保 CC2S 位设置为 01(输入捕获模式),并且 IC2FIC2PSC 位配置正确。


4. 中断或 DMA 传输完成标志



  • 如果你使用了 DMA 传输完成中断,确保在中断服务程序中正确处理了数据,并且没有错误地停止定时器或 DMA。

  • 如果使用了中断,确保在中断服务程序中正确清除中断标志。


5. 硬件连接



  • 确保外部信号正确连接到 TIM4_CH2 引脚,并且信号质量良好,没有噪声或干扰。


6. 代码实现



  • 检查生成的代码,确保所有配置都正确应用。特别是 TIM4 和 DMA 的初始化部分。

  • 如果你在代码中手动修改了某些寄存器,确保这些修改不会影响定时器或 DMA 的正常工作。


7. 调试



  • 使用调试工具(如 STM32CubeIDE 的调试器)来检查 TIM4 和 DMA 的状态寄存器,看看是否有错误标志被置位。

  • 通过调试器观察 TIM4->CCR2 的值,看看它是否在每次捕获后都更新。


示例代码片段


以下是一个简单的代码片段,展示如何配置 TIM4 和 DMA 进行输入捕获:


// TIM4 初始化
TIM_HandleTypeDef htim4;

void TIM4_Init(void) {
    TIM_IC_InitTypeDef sConfigIC = {0};

    htim4.Instance = TIM4;
    htim4.Init.Prescaler = 0;
    htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim4.Init.Period = 0xFFFF;
    htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_IC_Init(&htim4) != HAL_OK) {
        // 错误处理
    }

    sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
    sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
    sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
    sConfigIC.ICFilter = 0;
    if (HAL_TIM_IC_ConfigChannel(&htim4, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) {
        // 错误处理
    }

    // 配置 DMA
    HAL_TIM_IC_Start_DMA(&htim4, TIM_CHANNEL_2, (uint32_t*)&captureBuffer, CAPTURE_BUFFER_SIZE);
}

// DMA 初始化
void DMA_Init(void) {
    __HAL_RCC_DMA1_CLK_ENABLE();

    hdma_tim4_ch2.Instance = DMA1_Stream1;
    hdma_tim4_ch2.Init.Request = DMA_REQUEST_TIM4_CH2;
    hdma_tim4_ch2.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_tim4_ch2.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim4_ch2.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim4_ch2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_tim4_ch2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_tim4_ch2.Init.Mode = DMA_CIRCULAR;
    hdma_tim4_ch2.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_tim4_ch2) != HAL_OK) {
        // 错误处理
    }

    __HAL_LINKDMA(&htim4, hdma[TIM_DMA_ID_CC2], hdma_tim4_ch2);
}

// 主函数
int main(void) {
    HAL_Init();
    SystemClock_Config();
    TIM4_Init();
    DMA_Init();

    HAL_TIM_Base_Start(&htim4);

    while (1) {
        // 主循环
    }
}

总结


通过检查触发源配置、DMA 模式、定时器配置以及代码实现,你应该能够解决只能执行一次捕获的问题。如果问题仍然存在,建议使用调试工具进一步分析硬件和软件的状态。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分