硬件定时器在第一次使用时立即完成。 STM32F303VC

Hardware timer instantly completes when first used. STM32F303VC

我正在尝试在 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_CR1 寄存器中的 URS 位,这会导致更新 interrupt/DMA 请求仅在柜台 overflow/underflow 上发行。这当然不行。

我觉得我需要 reset/set 某个地方有一个 bit 以便让计时器在我第一次启用它时按预期运行。

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

The new prescaler ratio is taken into account at the next update event.

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

In upcounting mode, the counter counts from 0 to the auto-reload value (content of the TIMx_ARR register), then restarts from 0 and generates a counter overflow event. An Update event can be generated at each counter overflow or by setting the UG bit in the TIMx_EGR register (by software or by using the slave mode controller).

因此,在设置 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...