I'm new to the world of embedded and I'm implementing a short, long and two-click on a button logic in my project on a stm32f051
I'm having a problem with the timer interrupt, I want it to generate the interrupt when the Counter Value (TIM14->CNT) resets ONLY by overflow.
When I click on the button, it enters the external interrupt (EXTI2_3_IRQHandler) which then starts Timer14, if the button is released, it falls back to the interrupt which will then stop the counter and reset the count. My logic is implemented like this:
void EXTI2_3_IRQHandler(void)
{
HAL_NVIC_ClearPendingIRQ(EXTI2_3_IRQn); //Clear nvic interrupt flag
HAL_GPIO_EXTI_IRQHandler(SWITCH_Pin); //Clear gpio interrupt flag
if (HAL_GPIO_ReadPin(SWITCH_GPIO_Port, SWITCH_Pin) != GPIO_PIN_SET) //high level indicates switch is not being pressed
{
HAL_TIM_Base_Start_IT(&htim14); //Initializes the 3s timer count
}else{
HAL_TIM_Base_Stop_IT(&htim14);
TIM14->CNT = 0;
}
}
I noticed a "bug" that when I just click a short click, just the first time, it falls on the external interrupt and starts the timer, when the external interrupt ends it goes straight to the timer interrupt, which then goes to the callback where I increment the counter that the button was held down for 3 seconds. After this bug it works as expected, it only increments the counter if it was pressed for more than 3 seconds.
Reviewing the reference manual (https://www.st.com/resource/en/reference_manual/dm00031936-stm32f0x1stm32f0x2stm32f0x8-advanced-armbased-32bit-mcus-stmicroelectronics.pdf), page 459, I found the following information:
"Interrupt generation on the following events: – Update: counter overflow, counter initialization (by software)"
More details about my TIM14 setup (HCLK = 48Mhz) and callback function. Initialization TIM14:
static void MX_TIM14_Init(void) {
/* USER CODE BEGIN TIM14_Init 0 */
/* USER CODE END TIM14_Init 0 */
/* USER CODE BEGIN TIM14_Init 1 */
/* USER CODE END TIM14_Init 1 */
htim14.Instance = TIM14;
htim14.Init.Prescaler = 8000;
htim14.Init.CounterMode = TIM_COUNTERMODE_UP;
htim14.Init.Period = 18000;
htim14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim14) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM14_Init 2 */
/* USER CODE END TIM14_Init 2 */
}
And the timer callback function:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM16) {
HAL_IncTick();
if(Get_ButtonPressedValue() == TRUE || Get_ButtonPressedState() != NO_PRESS)
{
FSM_Button_Pressed();
}
}
/* USER CODE BEGIN Callback 1 */
if (htim->Instance == TIM14) {
if (HAL_GPIO_ReadPin(SWITCH_GPIO_Port, SWITCH_Pin) != GPIO_PIN_SET) //high level indicates switch is not being pressed
{
ui16CounterTIM14++;
Set_FlagTim14CntFinished(TRUE);
}
}
/* USER CODE END Callback 1 */
}
I've tried to put a breakpoint on the start of the timer and check the registers that are changed and find the ones that make sense to enter the timer interrupt by counter initialization. I've tried to change the values to zero, in the SFRs tab of the STM32F0x1 (Special Function Registers), since the register has write permission (Access permission: RW) and even so after the short click it registers as if it were a click from 3 seconds.
Before HAL_TIM_Base_Start_IT(&htim14) I only have the SR->UIF (update interrupt flag) at 1. And the PSC and ARR values configured in Init.
After the HAL_TIM_Base_Start_IT(&htim14) it has a value of CNT (>2000), the PSC and ARR values configured in Init, and the following reg in value 1:
- CR1->CEN (Counter enable)
- DIER->UIE (Update interrupt enable)
- SR->UIF (Update interrupt flag)
What should I do to not fall into this counter initialization interrupt?