2018-07-04 01:36 AM
I am working on a 3 channel frequency counter on STM32F446RE. I am displaying the values on an LCD 20x4 display. The LCD driver uses TIM1 in order to generate the microsecond and millisecond delays. I am also using TIM4 in order to interrupt normal system operation every 1 second, and print the current values stored in the frequency variables. But inside the timer interrupt TIM1 is not working. It get stuck in the loop,
static void LCD1602_TIM_MicorSecDelay(uint32_t uSecDelay)
{ TIM1->ARR = uSecDelay-1; TIM1->SR &= ~(0x0001); // Clear UEV flag TIM1->CR1 |= 1UL; while((TIM1->SR&0x0001) != 1); // (THIS IS THE LOOP IT GETS STUCK IN)}The timer configuration in the driver is:
static void LCD1602_TIM_Config(void)
{ RCC_ClkInitTypeDef myCLKtypeDef; uint32_t clockSpeed; uint32_t flashLatencyVar; HAL_RCC_GetClockConfig(&myCLKtypeDef, &flashLatencyVar); if(myCLKtypeDef.APB2CLKDivider == RCC_HCLK_DIV1) { clockSpeed = HAL_RCC_GetPCLK1Freq(); } else { clockSpeed = HAL_RCC_GetPCLK1Freq()*2; } clockSpeed *= 0.000001; //Enable clock for TIM2 timer RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // 0x1 //Set the mode to Count up TIM1->CR1 &= ~(0x0010); //Enable Update Event TIM1->CR1 &= ~(0x0001); //Update request source TIM1->CR1 &= ~(1UL << 2); // Set bit 3 High to enable One-Pulse mode TIM1->CR1 |= (1UL << 3); //Set the Prescalar TIM1->PSC = clockSpeed-1; //Set and Auto-Reload Value to delay the timer 1 sec TIM1->ARR = 10-1; // The Flag sets when overflows //Event generation handling to reset the counter TIM1->EGR = 1; //Update generate auto TIM1->SR &= ~(0x0001); //Clear Update interrupt flag}static void LCD1602_TIM_MicorSecDelay(uint32_t uSecDelay){ TIM1->ARR = uSecDelay-1; TIM1->SR &= ~(0x0001); // Clear UEV flag TIM1->CR1 |= 1UL; while((TIM1->SR&0x0001) != 1);}The Interrupt is shown below too:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{freq_disp();}With the interrupt being handled by an interrupt handler.
2018-07-04 05:13 AM
Couple of observations, there are more efficient ways to do register level programming, the SR should be reset with a Write, not a RMW operation.
Instead of using the TIM like this, consider just configuring it in a maximal free running mode, where ARR=0xFFFF, it ticks at 1 MHz, and you observed the elapse of micro-seconds by doing a delta computation of CNT. This will be both interrupt and thread safe.