0
\$\begingroup\$

I'm learning to programm on an STM32F7 46 G Discovery board using Eclipse as an IDE and STM32CubeMX. I'm trying to set a timer (currently TIM2) to one second without using an ISR. I'd like to get a tick from the timer every second.

Below is what I tried so far:

#include "main.h"
#include "stm32f7xx_hal.h"  

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);    

int main(void)
{
    HAL_Init();
    SystemClock_Config(); 
    MX_GPIO_Init();
    MX_TIM2_Init();
    __TIM2_CLK_ENABLE();

   while (1)
   {
       HAL_TIM_PeriodElapsedCallback(&htim2);
   }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim2)
{
    if (htim2->Instance==TIM2) //check if the interrupt comes from TIM2
        {
           HAL_GPIO_TogglePin(ARDUINO_D2_GPIO_Port,ARDUINO_D2_Pin);
        }
}

static void MX_TIM2_Init(void) /* TIM2 init function */
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 41999; //max 65 536
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = 0;
  HAL_TIM_Base_Init(&htim2);
  HAL_TIM_Base_Start(&htim2);

  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;


   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
      {
        _Error_Handler(__FILE__, __LINE__);
      }
}

I know that the MCU runs at 42MHz which finally makes the clock run at 84MHz with PLL and I think I already set the Prescaler and the Period (to fix the autoreload time) values accordingly.

Thanks for answering and sorry for any English mistake (it's not my first language)

\$\endgroup\$
  • \$\begingroup\$ What result do you get when you run your current code? \$\endgroup\$ – Dean Franks Nov 30 '17 at 18:47
  • \$\begingroup\$ The current code switches the connected LED on but only once. I see two options 1) the led blinks too fast for us to see it (which would mean I made a mistake in the timer settings) 2) the line : HAL_GPIO_TogglePin(ARDUINO_D2_GPIO_Port,ARDUINO_D2_Pin); is only executed once \$\endgroup\$ – Valentin CHOUETTE Nov 30 '17 at 20:57
2
\$\begingroup\$

You don't need to call HAL_TIM_PeriodElapsedCallback() function in while(1) loop. Because it works in non-blocking mode! Instead, you can do something like this if you want to toggle led every one second.

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   /*Include channel assertion as you did above */
   HAL_GPIO_TogglePin(ARDUINO_D2_GPIO_Port,ARDUINO_D2_Pin);
}

You can simply remove the Callback function call in main().

I don't think you need to enable the clock separately in main() function. It will be enabled in *_hal_msp.c file. Verify that "HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)" function has been initialized in *_hal_msp.c file in ./Src folder.

Your timer configuration looks fine for me but for Timer_Clock configuration to be precise, calculate Prescaler value from SystemCoreClock value.

and finally, if you want to trigger an interrupt or create ISR for every 1 second, you can simply use "HAL_TIM_Base_Start_IT()".

Edit: So, I played with it myself a bit and have successfully implemented your program on my STM32E407 board and here is the link! My observation is that you have to start the TIME_BASE in interrupt mode i.e include

  /*##-2- Start the TIM Base generation in interrupt mode **/ 
  if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK)
  {
     /* Starting Error */
     _Error_Handler(__FILE__, __LINE__);
   }

and start TIM2_IRQHandler() in *_it.c and include NVIC priority in *hal_msp.c.

Even I do not particularly know the reason as to why you have to use in interrupt mode. But I guess the Callback function is ISR related.

Edit2: Yes! Check *_tim.c in stdPheripharal library. The PeriodElapsedCallback function is called only in HAL_TIM_IRQHandler(). So, without using interrupt handler, the callback function returns nothing.

\$\endgroup\$
  • \$\begingroup\$ First of all sorry the typo, I edited the post. However, I didn't have the mistake in the IDE. I checked the "HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)" in *_hal_msp.c file in ./Src folder and it is indeed initialized. \$\endgroup\$ – Valentin CHOUETTE Dec 1 '17 at 7:45
  • \$\begingroup\$ Also, I tried commenting the call of the Callback in the main as well as the clock enabling always in the main. Finally, just to be sure, what is the "channel assertion" precisely ? Anyway thanks for answering and sorry for any trivial question I'm a real beginner here. \$\endgroup\$ – Valentin CHOUETTE Dec 1 '17 at 7:53
  • \$\begingroup\$ if (htim2->Instance==TIM2) that is what I meant by channel assertion! Anyway, it should work with your code! Let me check with my stm32f4 board! I will report back to you soon! \$\endgroup\$ – charansai Dec 1 '17 at 8:10
  • \$\begingroup\$ I do not have enough privilege to just comment the suggestions, so I put it as an answer! I could suggest you few more things after I test the program \$\endgroup\$ – charansai Dec 1 '17 at 8:12
  • \$\begingroup\$ @ValentinCHOUETTE It doesn't matter where you put the callback function before or after main(); Check once again! \$\endgroup\$ – charansai Dec 1 '17 at 19:25
1
\$\begingroup\$

Finally solved my issue. Three points were wrong :

  • As suggested by Charansai the Callback function must not be called in the loop while(1) (here it stays empty)
  • The line HAL_TIM_Base_Start_IT(&htim2); must be added
  • The Callback must be put before the main()

In the end the code looks like this :

/* Includes     ---------------------------------------------------------*/
#include "main.h"
#include "stm22f7xx_hal.h"

/*Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;

/*Protypes  ---------------------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)  ;

/*Private functions ---------------------------------------------------------*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance==TIM2) //check if the interrupt comes from TIM2
        {
             HAL_GPIO_TogglePin(ARDUINO_D2_GPIO_Port,ARDUINO_D2_Pin);
        }
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM2_Init();

  HAL_TIM_Base_Start_IT(&htim2);

  while (1)
  {
  }
}

/* TIM2 init function */
static void MX_TIM2_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 41999;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

Thanks for answering and highlighting some issues

\$\endgroup\$

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.