【问题标题】:Hardware timer instantly completes when first used. STM32F303VC硬件计时器在首次使用时立即完成。 STM32F303VC
【发布时间】:2021-03-29 11:43:32
【问题描述】:

我正在尝试在STM32F303 Discovery 板上以单脉冲模式 (OPM) 设置和使用 TIM2 外设。

我遇到的问题是计时器在启用后立即完成。

此时我没有使用interrupt,我只是轮询TIM2_SR(状态寄存器)UIF 位以确定计时器是否已完成。

这只会在我第一次启用计时器时发生,如果我再次使用计时器,它会正常工作(不会立即完成)。

我尝试在启用定时器之前重置TIM2_CNT 寄存器,但结果是一样的。

use cortex_m_rt::entry;
use stm32f3xx_hal::pac;


#[entry]
fn main( ) -> ! {
    let p = pac::Peripherals::take( ).unwrap( );

    p.RCC.apb1enr.modify( | _, w | w.tim2en( ).set_bit( ) );

    p.TIM2.cr1.write( | w | w
        .urs( ).set_bit( )
        .opm( ).set_bit( )
        .cen( ).clear_bit( ) );

    // I've tried resetting the CNT register at this point
    // in the application but the result was the same. 
    
    // Set the prescaler based on an 8MHz clock.
    p.TIM2.psc.write( | w | w.psc( ).bits( 7999 ) );

    // Here I initialize an LED (GPIOE). I've removed this code to 
    // keep the example as clean as possible.

    let delay = | duration | {         

        p.TIM2.arr.write( | w | w.arr( ).bits( duration ) ); 

        // I've also tried resetting the CNT register here 
        // but the result was the same.       
        p.TIM2.cr1.modify( | _, w | w.cen( ).set_bit( ) );

        while p.TIM2.sr.read( ).uif( ).bit_is_clear( ) { }

        p.TIM2.sr.write( | w | w.uif( ).clear_bit( ) );
    };

    // Enable LED.

    // This call instantly returns.
    delay( 3999 );

    // Disable LED.

    loop { }
}

上面的示例使 LED 闪烁,几乎没有延迟。 如果我改为使用无限循环,则计时器会在初始调用 delay 后按预期工作。

loop {

    // Enable LED.

    // The first call in the first loop iteration
    // returns instantly.
    delay( 3999 );

    // Disable LED.
    
    // This call, and every call here after correctly
    // returns after 4 seconds.
    delay( 3999 );
}

我在应用程序运行时检查了寄存器,一切似乎都设置正确。

  • TIM2_CNT 寄存器在启用定时器之前读取 0x0000_0000
  • TIM2_SR 寄存器中的UIF 位在启用定时器之前未设置
  • TIM2_PSC 寄存器读取正确的预分频器7999
  • TIM2_ARR 寄存器包含正确的自动重载值 3999
  • TIM_CR1 寄存器中的OPM 位设置正确

在另一个论坛上阅读了类似问题后,该答案中建议启用TIM2_CR1 寄存器中的URS 位,这会导致更新中断/DMA 请求仅在计数器上溢/下溢时发出。这当然行不通。

我感觉在某个地方需要重置/设置 bit,以便在我第一次启用它时让计时器按预期运行。

【问题讨论】:

    标签: rust timer embedded stm32


    【解决方案1】:

    好的,所以在重新阅读手册中有关计时器的部分后,我发现了以下内容:

    新的预分频比将在下一次更新事件中考虑。

    好的,那么如何通过软件生成更新事件,以便在启动计时器之前更新预分频器值。就在那时我发现了这个(重点是我的):

    在向上计数模式下,计数器从 0 计数到自动重载值( TIMx_ARR 寄存器),然后从 0 重新启动并产生计数器溢出事件。 可以在每次计数器溢出时或通过设置 TIMx_EGR 寄存器中的 UG 位来生成更新事件(通过软件或使用从模式控制器)。

    所以在设置prescaler 值之后,我在TIM2_EGR 寄存器中设置UG 位。

    // Set the prescaler based on an 8MHz clock.
    p.TIM2.psc.write( | w | w.psc( ).bits( 7999 ) );
    
    // Generate an update event so that the new prescaler
    // value gets loaded.
    p.TIM2.egr.write( | w | w.ug( ).update( ) );
    

    在强制更新后,计时器每次都开始正常工作(包括第一次)。

    所以,总结一下我的问题RT*M...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多