STM32H750 - Timer preload has no effect - Interrupt

Kisen

Member
Hi.
I am hoping someone can solve this problem im having.

I have Timer3 running and trying to get a 1 second interrupt. However i am getting strange behaviour that i simply dont understand.

With the below code my interrupt appears to be firing but its too fast. When i scope the LED pin its toggling at 33.3Khz. This suggests to me that my clock prescaler was wrong.
This is where it gets odd for me. Changing the TIM3->ARR i get a change on the scope that is sensible, i.e increase the value and get a slower interrupt.
However, changing the prescaler does nothing at all. it doesnt matter what value i enter nothing changes.

I have been trying for a couple of days to find the fix for this when i came across a post that said the order of the prescaler and reload was important. I cant see how but i thought i would try it. So i loaded ARR value then PSC value.
This resulted in me getting a fixed 4 second interrupt. Changing either the PSC or ARR has no effect.

So my question.
Is there a reason why my code as below seems to ignore the PSC value entirely?

Further info.
My clock is startup default. So 4Mhz.
I have tried polling instead of interrupt, and i seem to get a reasonable 1 second blink. PSC = 3, ARR = 9999.
I have tried a different timer (Timer4) and get the same result as i do on Timer3.


C:
#include "stm32h7xx.h"

static volatile uint8_t led_on = 0;

void TIM3_IRQHandler(void)
{
  /* if UIF flag is set */
  if(TIM3->SR & (1<<0))
  {
    if( led_on == 0)
    {
            led_on = 1;
    }
    else
    {
            led_on = 0;
    }
        
        /* Clear the Interrupt Status */
        TIM3->SR &= ~(1 << 0);
  }
}

int main(void)
{
    // GPIO SETUP CODE
    
    RCC->AHB4ENR |= (1<<4);                            // Enable GPIOE clock
    GPIOE->MODER &= ~((1<<7) | (1<<6));        // Reset PE3
    GPIOE->MODER |= (0<<7) | (1<<6);        // Pin PE3(bits 5:4) as Output (01)
    
    GPIOE->OTYPER &= ~(1<<3);            // Set PE3 as Push-Pull
    
    // Speed register
    
    // pull up / pull down
    
    
    // TIMER 3 SETUP CODE
    
    RCC->APB1LENR |= (1 << 1);        // Enable the APB clock FOR TIM3
    
    TIM3->PSC = 3999;    // Setup prescaler - Req Freq = (CLK / (PSC + 1)) 1000 = 4000000 / 4000
    TIM3->ARR = 999;
    
    //TIM3->CR1 &= ~(1<<1);        // Clear UDIS bit - MADE NO CHANGE
    TIM3->CR1 |= (1<<2);        // Set URS bit - MADE NO CHANGE
    TIM3->EGR |= (1<<0);         // Update prescaler
    //TIM3->CR1 &= ~(1<<4);        // Clear DIR bit - MADE NO CHANGE
    
    /* Enable the Interrupt */
  TIM3->DIER |= (1 << 0);
    
    /* Clear the Interrupt Status */
  TIM3->SR &= ~(1 << 0);
    
    __NVIC_SetPriority(TIM3_IRQn, 2);   // Set TIM3 interrupt vector priority to 0
 
  __NVIC_EnableIRQ(TIM3_IRQn);    /* Enable NVIC Interrupt for Timer 3 */
    
    /* Enable TIM3 module */
    TIM3->CR1 = (1 << 0);
    
    
    while(1)
    {
        
        if(led_on)
    {
            GPIOE->ODR |= (1<<3);     // Set PE3 to ON
    }
    else
    {
            GPIOE->ODR &= ~(1<<3);     // Set PE3 to OFF
    }
    }
}
 
Thanks,
I have been looking further at this. I have taken a closer look at the registers while in debug. I noticed that if i breakpoint at TIM3->PSC then it started working as it should. Where with no breakpoint it didnt work.
I have found that the register was even being written unless it was in a breakpoint.

So as a quick fix i wrote that same register twice and it now works. Yay isnt coding fun haha.

Is there any reason why a register wont write? Do they need time to process or some other random reason?
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…