Leonidous
Leonidous

Reputation: 51

Interrupts on STM32F407G discovery Micro controller with HAL library to blink led

I am trying to create a metronome by using the led on my microcontroller board to blink at a specific number of beats per minute in order to figure out how to do hardware interrupts at specific intervals. I am using the HSI as the system clock.

The HSI runs at a default 16mhz. The expected behavior is that since 16mhz equals 16 million cycles per second, I want to get this to 1000 cycles per second to get a timer that runs on milliseconds (which is 1000 per second). So I divided HAL_RCC_GetHCLKFreq()/16000 and set the if statement (if(ms_counter >= 1000){}) to activate when ms_counter reaches 1000, the led blinks way to fast to see it. To actually get 60bpm with this setup I have to set the if statement to ms_counter if(ms_counter >= 200000){}, why?

The values I have input into the code below actually blink the led at 60bpm, but I am confused why these numbers work the way they do? It seems to behave this way ->

Divide 16mhz by 160,000 -> 100cps (cycles per second) -> Every 1ms = 100 interrupts? (ms_counter >= 100,000) is 60bpm

Divide 16mhz by 16,000 -> 1000cps (cycles per second) -> Every 1ms = 200 interrupts? (ms_counter >= 200,000) is 60bpm

If anyone can see what I'm doing wrong then it would be greatly appreciated! Or if this is working the way it's intended then I would appreciate some explanation... maybe I am missing something.

#include "stm32f4xx_hal.h"
#include "stm32f4xx.h"
#include <stdint.h>
#include <stdio.h>

void SystemClock_Config(void);
volatile uint32_t ms_counter = 0;  // A counter to track the number of milliseconds elapsed

int main(void)
{
    GPIO_InitTypeDef GPIOD_Params;
    __HAL_RCC_GPIOD_CLK_ENABLE();

    GPIOD_Params.Pin = GPIO_PIN_12; // Select pins 12 to 15
    GPIOD_Params.Mode = GPIO_MODE_OUTPUT_PP; // Set pins to push pull output mode
    GPIOD_Params.Speed = GPIO_SPEED_LOW; // Set low output speed
    HAL_GPIO_Init(GPIOD, &GPIOD_Params); // Initialise GPIOD according to parameters on GPIOD_Params
    HAL_Init();  // Initialize the HAL library
    SystemClock_Config();  // Set up the system clock (HSI as the source)
    // Configure SysTick to generate interrupts at 1ms intervals
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 16000);  // 1ms interval (HAL_RCC_GetHCLKFreq() == 16,000,000)

    // Main Loop
    while (1)
    {
        // Example: Toggle an LED every 500ms
        if (ms_counter >= 200000)
        {
            ms_counter = 0;  // Reset the counter
            HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);  // Toggle an LED
        }
        HAL_SYSTICK_Callback();
    }
}

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    // Configure HSI as the system clock source
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;  // Disable PLL
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
                                  RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;  // Set HSI as SYSCLK
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}

void HAL_SYSTICK_Callback(void)
{
    ms_counter++;  // Increment a custom counter
}

Upvotes: 0

Views: 77

Answers (1)

0___________
0___________

Reputation: 67835

You passed the wrong value. You set the interrupts frequency to 16k/sec. You need to pass the number of ticks per required period. You can easily figure it out yourself.

/**
  * @brief  Initialize the System Timer with interrupt enabled and start the System Tick Timer (SysTick): 
  *         Counter is in free running mode to generate periodic interrupts.
  * @param  TicksNumb: Specifies the ticks Number of ticks between two interrupts.
  * @retval status:  - 0  Function succeeded.
  *                  - 1  Function failed.
  */
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
   return SysTick_Config(TicksNumb);
}

So you want

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);

Upvotes: 4

Related Questions