1

I am using an STM32F042C4 and I want to set up timer for delay in µs. But when I set everything, I get a 2x larger. I am looking for any prescaler I could miss, but I have not found anything.

setting is:

//enable peripheral clock for TIM17
RCC->APB2ENR |= (0x1U << 18);

//Set HSI48 as clock source
while((RCC->CR2 >> 17) & 0x01U != 0x01U){      //wait for HSI48 ready
}
RCC->CR2 |= (0x1U << 16);                      //Enable HSI48
RCC->CFGR |= 0x00000003U;                      //Set HSI48 as clock source

//set TIM17 prescaler value for tick every 0,1 ms
TIM17->PSC = 4799;

//call delay func -> 10 000 should result in 1 sec delay, BUT I GET 2 SECONDS
void TIM17_delayUs(10000);

void TIM17_delayUs(uint16_t delay){
    TIM17->CNT = 0x0U;                                      //null counter
    TIM17->CR1 &= ~(0x1U << 7);                             //ARR buffer disable
    TIM17->ARR = (48*delay)/(prescaler+1);                  //set delay
    TIM17->CR1 |= (0x1U << 7);                              //ARR buffer enable

    TIM17->CR1 |= (0x1U << 0);                              //enable counter
    TIM17->ARR = 0xFFFFU;                                   //reset ARR

    while((TIM17->SR & 0x1U) == 0){                         //wait for overflow event
    }
    TIM17->CR1 &= ~(0x1U << 0);                             //disable timer
    TIM17->SR &= ~(0x1U << 0);                              //clear event flag
}

If I look to registers I can see AHB and APB prescalers are 1 so clock source for timer should be 48Mhz. And I cannot see another prescaler before timer counter, so where can be that problem?

Clock diagram for STM32F042

TIM17 block diagram

zx485
  • 28,498
  • 28
  • 50
  • 59

1 Answers1

1

I couldn't find the bug. But if the prescaler value is 4799, then TIM17->ARR = (48*delay)/(prescaler+1); line evaluates to 100, which seems wrong.

This code could have been written in a simpler way. Less code means lower possibility for errors. Forget about ARR, TIM start & stop and interrupt flags. Leave ARR at max (0xffff, default value). In other words, make TIM17 a free running timer, which is always enabled.

// TIM17 Settings
TIM17->PSC = 4799; // Set prescaler
TIM17->CR1 |= TIM_CR1_CEN; // Start timer
TIM17->EGR |= TIM_EGR_UG; // Generate update event for prescaler update

// Delay Function
delay100us(uint16_t us100) {
    uint16_t start = TIM17->CNT;
    while ((TIM17->CNT - start) < us100);
}
Tagli
  • 2,412
  • 2
  • 11
  • 14
  • 1
    Ok, I have got that bug. That line `TIM17->ARR = (48*delay)/(prescaler+1);` has two errors. At first, as you said, it is a bad formula and secondly, I forgot to save prescaler value in initFunc(). So I was dividing by 1 all the time. Thank you for your help :) – Daniel Šebík Jan 02 '21 at 11:23