1
\$\begingroup\$

I use an STM32F401C discovery board with STM32F401VCT6 microcontroller and want to set up a timer in one pulse mode, generating an interrupt after elapsed period. The interrupt handler is to toggle one of the outputs state.

I have generated the project, using STM32CubeMX, added the code starting timer and a callback to be invoked when an interrupt fires.

The callback:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  UNUSED(htim);
  HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}

The line starting the timer operation in one pulse mode:

HAL_TIM_OnePulse_Start_IT(&htim10, TIM_CHANNEL_ALL);

Unfortunately, the program does not work as desired - outputs' state is not toggled.

The whole code of my main.c file is attached below. Clock configuration: APB1 Timer clocks: 25 MHz APB2 Timer clocks: 50 MHz

Could you please tell me, if I have missed something in my program?

main.c:

#include "main.h"
#include "stm32f4xx_hal.h"

TIM_HandleTypeDef htim10;

void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_TIM10_Init(void);

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  //This code is never reached
  UNUSED(htim);
  HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM10_Init();

  HAL_TIM_OnePulse_Start_IT(&htim10, TIM_CHANNEL_ALL);

  while (1)
  {

  }
}

void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 50;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  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_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

static void MX_TIM10_Init(void)
{
  htim10.Instance = TIM10;
  htim10.Init.Prescaler = 50000;
  htim10.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim10.Init.Period = 1000;
  htim10.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim10) != HAL_OK)
  {
    Error_Handler();
  }

  if (HAL_TIM_OnePulse_Init(&htim10, TIM_OPMODE_SINGLE) != HAL_OK)
  {
    Error_Handler();
  }

}

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  __HAL_RCC_GPIOD_CLK_ENABLE();

  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

  GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}

void Error_Handler(void)
{
  while(1) 
  {
  }
}

Edit: I attach the rest of the code, I find relevant.

stm32f4xx_hal_msp.c:

#include "stm32f4xx_hal.h"

extern void Error_Handler(void);

void HAL_MspInit(void)
{
  //This function is called

  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

  /* System interrupt init*/
  /* MemoryManagement_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
  /* BusFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
  /* UsageFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
  /* SVCall_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SVCall_IRQn, 0, 0);
  /* DebugMonitor_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
  /* PendSV_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PendSV_IRQn, 0, 0);
  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
  //This function is called

  if(htim_base->Instance==TIM10)
  {
     __HAL_RCC_TIM10_CLK_ENABLE();
    HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
  }

}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
  //This function is not called
  if(htim_base->Instance==TIM10)
  {
    __HAL_RCC_TIM10_CLK_DISABLE();

    HAL_NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);

  }
}

stm32f4xx_it.c:

#include "stm32f4xx_hal.h"
#include "stm32f4xx.h"
#include "stm32f4xx_it.h"

extern TIM_HandleTypeDef htim10;

void SVC_Handler(void)
{

}

void PendSV_Handler(void)
{

}

void SysTick_Handler(void)
{
  HAL_IncTick();
  HAL_SYSTICK_IRQHandler();
}

void TIM1_UP_TIM10_IRQHandler(void)
{
  //This code is never reached
  HAL_TIM_IRQHandler(&htim10);
}
\$\endgroup\$
1
\$\begingroup\$

I have finally figured out, what was missing in my code.

Apart from HAL_TIM_OnePulse_Start_IT(), also HAL_TIM_Base_Start() has to be called in order to set up the timer operation in one pulse mode.

Now my main function looks like below and the interrupt is fired when after the set time.

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM10_Init();

  HAL_TIM_Base_Start(&htim10);
  HAL_TIM_OnePulse_Start_IT(&htim10, TIM_CHANNEL_1);

  while (1)
  {

  }
}
\$\endgroup\$
  • \$\begingroup\$ Are you sure about this, because for me it only works if I use HAL_TIM_Base_Start_IT(&htim10); in stead of HAL_TIM_Base_Start(&htim10); \$\endgroup\$ – Fry Feb 13 '18 at 16:45
0
\$\begingroup\$

You haven't shown us all the code. For example, where is the Timer and GPIO peripherals enabled? And where is the Timer interrupt enabled?

Typically with STM32Cube HAL applications, the functions like HAL_TIM_Base_Init() call another function like HAL_TIM_Base_MspInit(), which you may have to provide an implementation for. The xxx_MspInit() functions are typically implemented in a file called stm32xxxx_hal_msp.c. ST provides a template for this file with the HAL but I believe the expectation is that you will copy the template to your project file and customize it. (I'm not familiar with the STM32CubeMX tool, which might do some of this automatically.)

Typically within HAL_TIM_Base_MspInit() in stm32xxxx_hal_msp.c is where you will enable the timer and the timer interrupt. That code will look something like this:

    // Enable the peripheral clock.
    __HAL_RCC_TIM10_CLK_ENABLE();

    // NVIC configuration for the TIM10 interrupt.
    HAL_NVIC_SetPriority(TIM10_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(TIM10_IRQn);

Then you also need to provide an implementation for the timer interrupt handler. Typically this is done in a file called stm32xxxx_it.c. This is another file provided as a template with the HAL but you're expected to customize it in your project directory. (And again, STM32CubeMX may do some of this automatically.)

/**
* @brief  This function handles TIM10_IRQHandler interrupt request.
* @param  None
* @retval None
*/
void TIM10_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim10);
}

It's HAL_TIM_IRQHandler() which then calls your HAL_TIM_PeriodElapsedCallback() function.

So make sure you've enabled the timer and the timer interrupt in HAL_TIM_Base_MspInit(). Then make sure you've provided an implementation for TIM10_IRQHandler() which calls HAL_TIM_IRQHandler(). Then use the debugger to step through the code. Set breakpoints in HAL_TIM_Base_MspInit() and TIM10_IRQHandler() and HAL_TIM_PeriodElapsedCallback() to figure out what is working and what is not working.

\$\endgroup\$
  • \$\begingroup\$ I have attached the rest of the code, I found important to the first post. I have also added comments marking, if particular function was called or not. All the functions, you have mentioned were called properly by the code generated with CubeMX. \$\endgroup\$ – Deoksyryboza Mar 14 '17 at 17:14
  • \$\begingroup\$ @Deoksyryboza You have calls to both HAL_TIM_Base_Init() and HAL_TIM_OnePulse_Init(). I think you should use only one or the other. Try removing the call to HAL_TIM_Base_Init(). Does the call to HAL_TIM_OnePulse_Init() succeed? Does HAL_TIM_Base_MspInit() still get called from HAL_TIM_OnePulse_Init()? \$\endgroup\$ – kkrambo Mar 14 '17 at 19:08
  • \$\begingroup\$ @Deoksyryboza After further review, it looks like there is a HAL_TIM_OnePulse_MspInit() that should be implemented in stm32f4xx_hal_msp.c instead of HAL_TIM_Base_MspInit(). \$\endgroup\$ – kkrambo Mar 14 '17 at 19:10
  • \$\begingroup\$ Removing the call to HAL_TIM_Base_Init(), did not help. The call to HAL_TIM_OnePulse_Init() succeeded. HAL_TIM_Base_MspInit() was not called. Implementing HAL_TIM_OnePulse_MspInit() instead of HAL_TIM_Base_MspInit() in stm32f4xxx_hal_msp.c did not help too. \$\endgroup\$ – Deoksyryboza Mar 15 '17 at 5:51
  • \$\begingroup\$ @Deoksyryboza Here's another idea. I think you may need to call HAL_TIM_OnePulse_ConfigChannel() in order to use the timer in one pulse mode. See the HAL documentation. \$\endgroup\$ – kkrambo Mar 16 '17 at 1:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.