‎2018-09-11 03:56 AM
I'm just starting to learn how to program ARM microcontrollers using ST's HAL. So I have this code which generates a 1khz and 20khz signal using a timer in output compare mode. That all works well and I tested it with a scope and it's as expected. The issue is with HAL_TIM_PeriodElapsedCallback() which should get called when whenever the timer has overflown and toggle an LED. The LED's configuration is correct.HAL_TIM_PeriodElapsedCallback() gets called by HAL_TIM_IRQHandler(&htim3); which is called whenever an interrupt for timer3 is fired such as when the timer overflows. HAL_TIM_IRQHandler(&htim3); also gets called often when the output compare register matches that of the timers 'count' register and it calls HAL_TIM_OC_DelayElapsedCallback(). This all works, so I know the timer3 interrupt is configured properly but I just cant figure out why when the timer overflows the correct callback doesn't get called. What I'm guessing is that the interrputs fired by the Output Compare somehow mess with the overflow interrupt. I've also tried using a debugger and following the code, but HAL_TIM_OC_DelayElapsedCallback() is just skipped. I've included my main() as well as the relevant code from the HAL_Timer library which handles all interrupts. Please help me debug this! PS. Nucleo_BSP_Init(); simply configures the clock and the GPIO so I won't put this code, since I know the LED works and the clock is configured using CubeMX so that should also be fine.
----------------MAIN CODE --------------------
#include "stm32f4xx_hal.h"
#include <nucleo_hal_bsp.h>
#include <string.h>
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;
void MX_TIM3_Init(void);
uint16_t computePulse(TIM_HandleTypeDef *htim, uint32_t chFrequency) {
uint32_t timFrequency= HAL_RCC_GetPCLK1Freq() / (htim->Instance->PSC + 1);
return (uint16_t)(timFrequency / chFrequency);
}
volatile uint16_t CH1_FREQ = 0;
volatile uint16_t CH2_FREQ = 0;
int main(void) {
HAL_Init();
Nucleo_BSP_Init();
MX_TIM3_Init();
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1);
HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_2);
while (1);
}
/* TIM3 init function */
void MX_TIM3_Init(void) {
TIM_OC_InitTypeDef sConfigOC;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 2;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_OC_Init(&htim3);
CH1_FREQ = computePulse(&htim3, 1000);
CH2_FREQ = computePulse(&htim3, 20000);
sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
sConfigOC.Pulse = CH1_FREQ;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
sConfigOC.Pulse = CH2_FREQ;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) {
uint32_t pulse;
/* TIMx_CH1 toggling with frequency = 1KHz */
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
pulse = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
/* Set the Capture Compare Register value */
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, (pulse + CH1_FREQ));
}
/* TIM2_CH2 toggling with frequency = 20KHz */
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
pulse = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
/* Set the Capture Compare Register value */
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_2, (pulse + CH2_FREQ));
}
}
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef* htim_base) {
GPIO_InitTypeDef GPIO_InitStruct;
if(htim_base->Instance==TIM3) {
__TIM3_CLK_ENABLE();
/**TIM3 GPIO Configuration
PA6 ------> TIM3_CH1
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
}
void TIM3_IRQHandler(void) {
HAL_TIM_IRQHandler(&htim3);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance == TIM3){
// HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
}
IRQ Handler code which gets callled whenever an interupt is fired.
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
/* Capture compare 1 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET)
{
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
/* Input capture event */
if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
}
/* Capture compare 2 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
/* Input capture event */
if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
/* Capture compare 3 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
/* Input capture event */
if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
/* Capture compare 4 event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
/* Input capture event */
if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
{
HAL_TIM_IC_CaptureCallback(htim);
}
/* Output compare event */
else
{
HAL_TIM_OC_DelayElapsedCallback(htim);
HAL_TIM_PWM_PulseFinishedCallback(htim);
}
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
}
/* TIM Update event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
HAL_TIM_PeriodElapsedCallback(htim);
}
}
/* TIM Break input event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
HAL_TIMEx_BreakCallback(htim);
}
}
/* TIM Trigger detection event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
HAL_TIM_TriggerCallback(htim);
}
}
/* TIM commutation event */
if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET)
{
if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET)
{
__HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
HAL_TIMEx_CommutationCallback(htim);
}
}
}
‎2018-09-11 04:26 AM
I don't Cube/CubeMX, but do you have the update interrupt enabled in TIMx_DIER?
JW
‎2018-09-12 06:26 AM
Hi @FFuma​ ,
The "HAL_TIM_OC_Start_IT" does not enable the overflow interrupt . This should be done before enabling the timer using:
__HAL_TIM_ENABLE_IT(&tim3, TIM_IT_UPDATE );
Khouloud.
‎2018-09-21 03:57 AM
@Community member​ @Khouloud GARSI​ Thanks guys very helpful! I enabled the overflow interrupt and everything worked fine :)
‎2018-09-21 03:59 AM
You're welcome ;)
‎2020-03-17 04:16 AM
Dear
Khouloud GARSI (ST Employee)
you say :
"The "HAL_TIM_OC_Start_IT" does not enable the overflow interrupt . This should be done before enabling the timer using:
__HAL_TIM_ENABLE_IT(&tim3, TIM_IT_UPDATE );
"
where is write this information?
I think is the site where are other infos that I'm searching.
many thanks
Luciano
‎2020-04-07 03:20 PM
If you take a look at HAL_TIM_OC_Start_IT in the stm32fxxx_hal_tim.c, you will find that only the Capture/Compare interrupt is enabled. Not the overflow interrupt.
/* Enable the TIM Capture/Compare 1 interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
‎2020-09-26 12:15 PM
Thanks, that solved my problem :grinning_face:
‎2022-09-07 07:56 AM
Perfect solutions thanks for the answer.
solved my problem