1
\$\begingroup\$

I've been trying for 2 days now to get my Output Compare to trigger a function.

I've been reading up on it, and there is a callback function that, from what I understand, is triggered when an output compare is triggered: HAL_TIM_OC_DelayElapsedCallback()

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim){ if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){ HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET); } if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4){ HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET); } } 

When I put a breakpoint on this function, I noticed that my program never entered it, even though I have 2 outputs compare that are triggered every second.

I don't know where to look anymore,

So I have my timer3 with channels 2 and 4 in output compare, in toggle on match mode. My timer has a period of 1000 and my channel 2 has a pulse at 250 and channel 750.

The timer channels are connected to the pins of the 2 LEDs, when the OUTPUT compare is triggered, it turns the LEDs on and off at regular intervals.

My idea was that with the output compare callback function when an output compare is triggered, it turns on the LEDs, so there is no need to connect the timer channels directly to the PINS of the 2 LEDs.

 /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdio.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ TIM_HandleTypeDef htim3; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM3_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM3_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_2); HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_4); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 15; RCC_OscInitStruct.PLL.PLLN = 144; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 5; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) { Error_Handler(); } } /** * @brief TIM3 Initialization Function * @param None * @retval None */ static void MX_TIM3_Init(void) { /* USER CODE BEGIN TIM3_Init 0 */ /* USER CODE END TIM3_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; /* USER CODE BEGIN TIM3_Init 1 */ /* USER CODE END TIM3_Init 1 */ htim3.Instance = TIM3; htim3.Init.Prescaler = 16000; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 1000; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim3) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_Init(&htim3) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_TOGGLE; sConfigOC.Pulse = 250; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } sConfigOC.Pulse = 750; if (HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM3_Init 2 */ /* USER CODE END TIM3_Init 2 */ HAL_TIM_MspPostInit(&htim3); } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); /*Configure GPIO pin : PA5 */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim){ if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){ HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET); } if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4){ HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET); } } /* USER CODE END 4 */ 

!!! Note that my program doesn't initialize the LEDs, for the moment I just want to see in debug mode if my program enters the function when a compare output is triggered, and already that, it doesn't work...

EDIT :thank you for your answers, by modifying HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_2); by HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_2); and by activating the interrupts HAL_NVIC_EnableIRQ(TIM3_IRQn); my program enters the HAL_TIM_OC_DelayElapsedCallback function.

On the other hand, by wanting to create the RQHandler function,

void TIM3_IRQHandler(void){ HAL_TIM_IRQHandler(&htim3); } 

I get a first defined here error, I don't know if this function is useful for the rest of my problem:

Now that my program enters the callback function of the output compare, it doesn't seem to compare, I explain myself:

I thought the lines:

if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) 

were going to check if the output compare of channel 2 or 4 is enabled, and if so, do what's in my condition. But, that's not what happens.

My program always enters the conditions.

I did a test to verify this:

I changed the value of my comparative output from channel 4 to 1500. The period of my timer is 1000, so this compare output should never be triggered. But it still triggers, my program enters the condition : if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4) when it should not.

I don't know why, I still feel like I'm forgetting something lol

\$\endgroup\$
12
  • \$\begingroup\$ "I have 2 output compare that are triggered every second." > can you post that portion of code as well? Where you setup your timer and so on. Ideally, you should post the whole source code of your project. \$\endgroup\$ Commented Jan 26, 2021 at 12:55
  • \$\begingroup\$ Thanks, I just edited with the whole code \$\endgroup\$ Commented Jan 26, 2021 at 13:06
  • \$\begingroup\$ What do you use for debugging? \$\endgroup\$ Commented Jan 26, 2021 at 13:47
  • 1
    \$\begingroup\$ Hey OP, after a cursory look it seems to me that you do not even enable interrupts... Can you point out where that is happening? \$\endgroup\$ Commented Jan 26, 2021 at 14:57
  • 1
    \$\begingroup\$ @sylvaing See @brhans' answer to activate your interrupts and set an interrupt priority for it. Also, you might have to use HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_2); instead of HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_2);. Additionally, you could check the HAL and LL documentation ST has on their website. \$\endgroup\$ Commented Jan 26, 2021 at 23:20

2 Answers 2

2
\$\begingroup\$

There are (at least) 2 things missing from your code, both related to interrupts.

  1. You need to enable interrupts for the timer you're using:
HAL_NVIC_ClearPendingIRQ(TIM3_IRQn); // make sure that any pending interrupt is cleared HAL_NVIC_EnableIRQ(TIM3_IRQn); // Enable the interrupt 
  1. You need to create an Interrupt Handler function which calls the STM HAL library interrupt handler code:
// Timer 3 Interrupt Handler void TIM3_IRQHandler(void) { HAL_TIM_IRQHandler(&htim3); // call the STM32 HAL Timer IRQ Handler for tim3 } 
\$\endgroup\$
0
\$\begingroup\$

On the callback function, you made a mistake; you did not reset the LED in the callback function.

The callback function should be like this;

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim){ if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){ HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_SET); } if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4){ HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET); } } 

Setting Debug Pins

In the SYS Mode and Configuration you need to select Debug to Serial Wire.

Setting Debug Pins

\$\endgroup\$
5
  • \$\begingroup\$ Yes that's right, it should be like that, if my program would fit into this function ... \$\endgroup\$ Commented Jan 26, 2021 at 13:34
  • \$\begingroup\$ Is this solution wrong? \$\endgroup\$ Commented Jan 26, 2021 at 13:43
  • \$\begingroup\$ No it's not wrong, but that doesn't answer my question, because the program doesn't even fit into this function, and that's what I don't understand. \$\endgroup\$ Commented Jan 26, 2021 at 13:45
  • \$\begingroup\$ I just tried it and it gives me the same result, it doesn't go in the function. \$\endgroup\$ Commented Jan 26, 2021 at 14:28
  • \$\begingroup\$ Did you enable global interrupt of timers? \$\endgroup\$ Commented Jan 26, 2021 at 15:40

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.