No se puede inicializar el temporizador STM32 en un modo de pulso con ST HAL

1

Utilizo un tablero de descubrimiento STM32F401C con microcontrolador STM32F401VCT6 y quiero configurar un temporizador en un modo de impulso, generando una interrupción después del período transcurrido. El controlador de interrupciones es para alternar una de las salidas de estado.

He generado el proyecto, utilizando STM32CubeMX, agregue el temporizador de inicio del código y una devolución de llamada que se invocará cuando se dispare una interrupción.

La devolución de llamada:

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

La línea que inicia la operación del temporizador en un modo de pulso:

HAL_TIM_OnePulse_Start_IT(&htim10, TIM_CHANNEL_ALL);

Lamentablemente, el programa no funciona como se desea: el estado de las salidas no se alterna.

El código completo de mi archivo main.c se adjunta a continuación. Configuración del reloj: Relojes temporizadores APB1: 25 MHz Relojes temporizadores APB2: 50 MHz

¿Podría decirme, por favor, si me he perdido algo en mi programa?

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) 
  {
  }
}

Editar: Adjunto el resto del código, me parece relevante.

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);
}
    
pregunta Deoksyryboza

2 respuestas

1

Finalmente he descubierto lo que faltaba en mi código.

Además de HAL_TIM_OnePulse_Start_IT() , también se debe llamar a HAL_TIM_Base_Start() para configurar la operación del temporizador en un modo de pulso.

Ahora mi función principal se ve como a continuación y la interrupción se activa una vez transcurrida la hora establecida.

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)
  {

  }
}
    
respondido por el Deoksyryboza
0

No nos has mostrado todo el código. Por ejemplo, ¿dónde están habilitados los periféricos Timer y GPIO? ¿Y dónde está habilitada la interrupción del temporizador?

Por lo general, con las aplicaciones HAL de STM32Cube, las funciones como HAL_TIM_Base_Init() llaman a otra función como HAL_TIM_Base_MspInit() , para la cual es posible que tenga que proporcionar una implementación. Las funciones xxx_MspInit() se implementan normalmente en un archivo llamado stm32xxxx_hal_msp.c. ST proporciona una plantilla para este archivo con la HAL, pero creo que la expectativa es que usted copiará la plantilla a su archivo de proyecto y la personalizará. (No estoy familiarizado con la herramienta STM32CubeMX, que podría hacer algo de esto automáticamente).

Normalmente, dentro de HAL_TIM_Base_MspInit () en stm32xxxx_hal_msp.c es donde habilitará el temporizador y la interrupción del temporizador. Ese código se verá así:

    // 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);

Luego, también debe proporcionar una implementación para el controlador de interrupción del temporizador. Normalmente esto se hace en un archivo llamado stm32xxxx_it.c. Este es otro archivo proporcionado como plantilla con el HAL, pero se espera que lo personalice en el directorio de su proyecto. (Y nuevamente, STM32CubeMX puede hacer algo de esto automáticamente).

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

Es HAL_TIM_IRQHandler() que luego llama a su función HAL_TIM_PeriodElapsedCallback() .

Así que asegúrese de haber habilitado el temporizador y la interrupción del temporizador en HAL_TIM_Base_MspInit() . Luego, asegúrese de haber proporcionado una implementación para TIM10_IRQHandler() que llame a HAL_TIM_IRQHandler() . Luego usa el depurador para recorrer el código. Establezca puntos de interrupción en HAL_TIM_Base_MspInit() y TIM10_IRQHandler() y HAL_TIM_PeriodElapsedCallback() para averiguar qué funciona y qué no funciona.

    
respondido por el kkrambo

Lea otras preguntas en las etiquetas