2021-02-15 06:42 AM
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?
Solved! Go to Solution.
2021-02-15 07:38 AM
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.
2021-02-15 06:44 AM
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.
2021-02-15 06:47 AM
> 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
2021-02-15 06:51 AM
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
2021-02-15 07:03 AM
(RCC->ICSCR >> 8) Before writing = 64
(RCC->ICSCR >> 8) After writing = 75
2021-02-15 07:38 AM
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.