cancel
Showing results for 
Search instead for 
Did you mean: 

How PLL affects timer Pre-sclaer.

DJ1
Associate III

Below i have attached a code which enables the PLL freq of 72MHz using HSI of 16MHz. The issue is if I give a Timer pre-scaler of 36000-1 (I am using timer2, which in case of STM32F401RE is on APB1 bus so using a pre-scaler of 2 for APB1 which makes it 36MHz, thus a pre-scaler of 36000-1 will generate a delay of 1 ms). Desired outcome is to generate 1 ms timer delay but it is not 1 ms when tested with timer ARR is set 5000. I have already checked clock using MCO1 pin with a pre-scaler of 2 which gave 36MHz on DSO. When  i call a delay function by passing 5000 as timer ARR value, then i hardly get 2500 - 3000 ms delay.

Below is my RCC_Init() function, please let me know is there any other settings are needed for setting up timers using PLL. 

void tim_init()
{
TIM2_EN;
//TIM2->TIMx_PSC = 36000-1;
TIM2->TIMx_PSC = 16000-1;
//TIM2->TIMx_PSC = 80000-1;
//TIM2->TIMx_PSC = 72000 - 1;
}
 
void delay(uint16_t x)
{
TIM2->TIMx_ARR = x;
TIM2->TIMx_CNT = 0;
TIM2->TIMx_CR1 |= (1 << 0);
while(TIM2->TIMx_CNT < x);
}
void RCC_Init()
{
/*
* RCC Settings for setting upto 80MHz freq using HSI based PLL
*/
 
// Set PLL clock for MCO output
//RCC->CFGR |= (3 << 21);
// Set pre-scaler for MCO1 bcoz of Logic Analyzer
//RCC->CFGR |= (4 << 24);
 
 
 
// Power Settings
// Enable Power Setting;
RCC->APB1ENR |= (1 << 28);
// Set VSO to 3
PWR->PWR_CR |= (2 << 14);
// dummy Read
uint8_t dummy = PWR->PWR_CR;
 
 
// Program number of wait states to the Latency bits in ACR
FLASH->FLASH_ACR |= (2 << 0);
// Read Flash ACR
uint8_t dummy1 = FLASH->FLASH_ACR;
// Enable Pre-fetch
FLASH->FLASH_ACR |= (1 << 8);
// Enable Data Cache
FLASH->FLASH_ACR |= (1 << 10);
// Enable Instruction Cache
FLASH->FLASH_ACR |= (1 << 9);
 
#ifdef HSE
 
// Turn ON HSE
RCC->CR |= (1 << 16);
// Wait till ready
while(!(RCC->CR >> 17 & 1));
// Set HSE as PLL source
RCC->CFGR |= (1 << 22);
// Turn OFF HSI
RCC->CR &= ~(1 << 0);
// Enable Clock security CSS
RCC->CR |= (1 << 19);
 
 
#else
 
// Turn on HSI ON
RCC->CR |= (1 << 0);
// wait until HSI is ready
while(!(RCC->CR >> 1 & 1));
 
#endif
 
 
// Clear the default 192 setting
RCC->PLLCFGR &= ~(192 << 6);
// Set 200 to PLLN
RCC->PLLCFGR |= (216 << 6);
// Clear the default 16 setting
RCC->PLLCFGR &= ~(16 << 0);
// Set 8 to PLLM
RCC->PLLCFGR |= (8 << 0);
// Set PLLP to 6
RCC->PLLCFGR |= (2 << 16);
// Clear PLLQ
RCC->PLLCFGR &= ~(4 << 24);
// Set PLLQ to 9
RCC->PLLCFGR |= (9 << 24);
 
// Set Pre-scaler 2 for APB1 bus within 42MHz
RCC->CFGR |= (4 << 10);
 
// Turn on PLL from RCC CR Register
RCC->CR |= (1 << 24);
// Wait till PLL is ready
while(!(RCC->CR >> 25 & 1));
 
// SET PLL as system clock
RCC->CFGR |= (2 << 0);
// Wait until PLL Switch Status is SET
while(!(RCC->CFGR >> 2 & 2));
}
1 ACCEPTED SOLUTION

Accepted Solutions

As the TIM clock is 72MHz and you can't set PSC to 72000-1 (as it's only 16-bit), set it to 36000-1 and multiply value to be written to ARR by 2 (and don't forget to subtract 1).

JW

View solution in original post

12 REPLIES 12
Foued_KH
ST Employee

Hello @DJ1 , 

Have you tried using STM32CubeMX?

I suggest you to use STM32CubeMX , It helps you for the configuration of the STM32 peripherals and Clock configuration.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

I tried using CubeMx, but only for PLL config. In my code that is fine, but when i try to generate a delay of lets say for eg 1ms i get output of only 981 microseconds. Due to this mismatch i think entire delay is changing. Can it be due to HSI.

TDK
Guru

> when i try to generate a delay of lets say for eg 1ms i get output of only 981 microseconds

> Can it be due to HSI.

Yes, absolutely. You're seeing an error of 1.9%. Let's check the datasheet for the HSI:

TDK_0-1692969523489.png

So it guarantees ±1% at ambient before part is soldered. Soldering will change that some. You can adjust the HSI using HSITRIM to get it more accurate.

If you need good accuracy, crystal+HSE is going to be much more accurate.

Also be aware ARR is preloaded and there's probably better ways to do delays, but that is a side issue.

If you feel a post has answered your question, please click "Accept as Solution".

If you use APB prescaler other than 1, timer clock is 2x APB clock.

JW

Exactly, but the thing is if i kept APB1 pre-scaler as /2 (72MHz / 2 = 36 MHz) then APB1 timer clock should be 2*APB clock (still 72MHz), now if i want to generate a precise blocking delay of 1 ms than what shall be my Timer pre-scaler settings. 

Below i have mentioned once again:

void tim_init()
{
// Enable clock for timer 2
TIM2_EN; // will have to be used as PWM_FAN_2
// Generate 1ms delay from 16MHz clock, prescalar value is 16000-1
TIM2->TIMx_PSC = 36000;
}

 

void delay(uint16_t x)
{
TIM2->TIMx_ARR = x;
TIM2->TIMx_CNT = 0;
TIM2->TIMx_CR1 |= (1 << 0);
while(TIM2->TIMx_CNT < (x));
}
DJ1
Associate III

I understand the clock issue with HSI but as of now i am trying to test my system later we can switch the PLL input clock. As described, the issue lies when i try to test a blocking delay function, whose settings are

Pre-scaler  : 36000 and ARR is based on the user passes a value to a function. The thing is the timer is generating exactly half the time delay than expected. For eg: if i set 5 secs i get delay of 2.5sec. I think issue lies with Pre-scaling only. For that reason i set the TIMPRE bit in RCC_DCKCFGR register but no effect. 

What can be the solution for this, as if i am setting a timer interrupt for every 1ms and increment a variable uptill 5000 then everything is fine but i fell thats not the solution

As the TIM clock is 72MHz and you can't set PSC to 72000-1 (as it's only 16-bit), set it to 36000-1 and multiply value to be written to ARR by 2 (and don't forget to subtract 1).

JW

> For that reason i set the TIMPRE bit in RCC_DCKCFGR register but no effect.

If APB divider is 2, TIM clock is the same in either of RCC_DCKCFGR.TIMPRE setting. Read RCC_DCKCFGR.TIMPRE description in RM.

JW

True, but in CubeMX settings i can see APB1 clock settings different as well as Timer clock settings on that bus different 

DJ1_0-1693039449638.png

Thanks, the solution worked for me, but can you explain what does APB1 Timer clocks and APB1 peripheral clocks mean, like how are they different.