cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G070RB HSI16 Clock and clock calibration issues. Is there a clock calibration example without the need to use HSE or LSE clocks?

CP.Tang
Associate II

I am trying to acquire the amount of ticks a timer counts using a 50Hz signal (acquired from the mains using hardware). For this I use a EXTI8 interrupt where the 50Hz signal is sampled. I can see on the scope that this interrupts works perfectly (by measuring another pin where I toggle the output during the interrupt).

Using a timer I read the counter every interrupt using: LL_TIM_GetCounter(TIMx). And then proceed to reset the counter using LL_TIM_SetCounter(TIMx, 0). The timer is set to 500kHz using a prescaler that is a multiply of 16 (maximizing the accuracy).

However, the counter value I read every time is about 9700 ticks. Which is about 19.4ms = 51.55Hz. Which is way more than the datasheet provided accuracy of +/-0.5% of the 16MHz HSI.

After that. I proceed to use the HSI TRIM register and tried to calibrate the timer using my own mains frequency which was a perfect 50Hz signal. It resulted in having to increment the default 64 in the RCC->ICSCR register with 11 (which is about 11 * 0.3% = 3.3%!!) to acquire the desired amount of 10000 ticks to recreate the 50Hz.

What's more, when I proceeded to check all the timers on the STM32G070RB by generating 50Hz interrupts (Setting 160 as prescaler, and 2000 as the auto-reload value), I measured 51.25Hz on the oscilloscope on ALL timers.

So I needed to speed up the timer using the TRIM register to calibrate the Timer Counter, but then the timer interrupts are all messed up?

Am I doing something wrong?

1 ACCEPTED SOLUTION

Accepted Solutions
CP.Tang
Associate II

Problem solved.

In the reference manual: "Bits 15:0 PSC[15:0]: Prescaler value The counter clock frequency (CK_CNT) is equal to ***_PSC / (PSC[15:0] + 1). PSC contains the value to be loaded in the active prescaler register at each update event (including when the counter is cleared through UG bit "

Well seems like the +1 on the prescaler kind of messed everything up.

View solution in original post

5 REPLIES 5
CP.Tang
Associate II

FYI. When I do not touch the RCC->ICSCR register. The 50Hz I generate using the same settings, is about 49.6Hz. Which is still waaaaay off.

> What's more, when I proceeded to check all the timers on the STM32G070RB by generating 50Hz interrupts (Setting 160 as prescaler, and 2000 as the auto-reload value),

> I measured 51.25Hz on the oscilloscope on ALL timers.

Post code.

Also, read out and check/post the HSI trim value in RCC_ICSCR.

JW

CP.Tang
Associate II

Setting up TIM6 with LL drivers and CUBE MX

static void MX_TIM6_Init(void)
{
 
  /* USER CODE BEGIN TIM6_Init 0 */
 
  /* USER CODE END TIM6_Init 0 */
 
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
 
  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);
 
  /* TIM6 interrupt Init */
  NVIC_SetPriority(TIM6_IRQn, 0);
  NVIC_EnableIRQ(TIM6_IRQn);
 
  /* USER CODE BEGIN TIM6_Init 1 */
 
  /* USER CODE END TIM6_Init 1 */
  TIM_InitStruct.Prescaler = 160;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 2000;
  LL_TIM_Init(TIM6, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM6);
  LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM6);
  /* USER CODE BEGIN TIM6_Init 2 */
  /* Enable the update interrupt */
  LL_TIM_EnableIT_UPDATE(TIM6);
 
  /* Enable counter */
  LL_TIM_EnableCounter(TIM6);
  /* USER CODE END TIM6_Init 2 */
 
}

Inside the interrupt:

void TIM6_test(void) {
  LL_GPIO_SetOutputPin(NC_PC03_GPIO_Port, NC_PC03_Pin);
  LL_GPIO_ResetOutputPin(NC_PC03_GPIO_Port, NC_PC03_Pin);
}

Setting up TIM7 to count the amount of ticks when reading the EXTI8 Pin where a 50Hz signal is sampled on:

static void MX_TIM7_Init(void)
{
 
  /* USER CODE BEGIN TIM7_Init 0 */
 
  /* USER CODE END TIM7_Init 0 */
 
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
 
  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);
 
  /* USER CODE BEGIN TIM7_Init 1 */
 
  /* USER CODE END TIM7_Init 1 */
  TIM_InitStruct.Prescaler = 32;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 65535;
  LL_TIM_Init(TIM7, &TIM_InitStruct);
  LL_TIM_DisableARRPreload(TIM7);
  LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM7);
  /* USER CODE BEGIN TIM7_Init 2 */
  /* Enable counter */
  LL_TIM_EnableCounter(TIM7);
  /* USER CODE END TIM7_Init 2 */
}

Using the EXTI8 interrupt which is called at a frequency of (a real) 50Hz:

void ZeroCross(void) {
  ZeroCrossTiming[Index++] = LL_TIM_GetCounter(TIM7);
  LL_TIM_SetCounter(TIM7, 0);               // Reset the counter to 0
  if (Index == 16) {
    Index = 0;
  }
}

 NC_PC03_Pin = measured at 51.25Hz where I try to create the 50Hz signal

 ZeroCrossTiming = the 10000 ticks I expect after sampling the 50Hz signal

CP.Tang
Associate II

(RCC->ICSCR >> 😎 Before writing = 64

(RCC->ICSCR >> 😎 After writing = 75

CP.Tang
Associate II

Problem solved.

In the reference manual: "Bits 15:0 PSC[15:0]: Prescaler value The counter clock frequency (CK_CNT) is equal to ***_PSC / (PSC[15:0] + 1). PSC contains the value to be loaded in the active prescaler register at each update event (including when the counter is cleared through UG bit "

Well seems like the +1 on the prescaler kind of messed everything up.