I want to have a reliable delay function for my STM32 microcontroller, but all of the functions I've been working with are unreliable. The delay function I am using now has approximately 5 second delay, even though it shall be 1 second. Is the clock settings wrong in Keil? The easy solution would be to divide 1000 by 5, but I want to understand why my code is not working as it should.
#include "stm32f4xx_hal.h"
void configureLEDPins(void);
void delay_ms(uint16_t delay_ms);
void delay_us(uint32_t delay_us);
int main(void)
{
configureLEDPins();
while(1)
{
delay_ms(1000);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
}
}
void configureLEDPins(void)
{
GPIO_InitTypeDef myLeds;
myLeds.Mode = GPIO_MODE_OUTPUT_PP;
myLeds.Pin = (GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
__HAL_RCC_GPIOD_CLK_ENABLE();
HAL_GPIO_Init(GPIOD, &myLeds);
}
//Microsecond delay
void delay_us(uint32_t delay_us)
{
volatile unsigned int num;
volatile unsigned int t;
for (num = 0; num < delay_us; num++)
{
t = 11;
while (t != 0)
{
t--;
}
}
}
//Millisecond delay
void delay_ms(uint16_t delay_ms)
{
volatile unsigned int num;
for (num = 0; num < delay_ms; num++)
{
delay_us(1000);
}
}
It is not the right way to implement a delay function. The duration of delay_us
will highly depend on the compiler, on the compilation options but also on the execution context (prefetch, pipelining, interruptions, etc...).
The right way to go is to use one of STM32 timers, or the ARM Cortex Systick. There are different ways to use them but the easiest one (if you have a single thread and no power consumption issue) is to setup and launch the timer and poll for the appropriate status bit. Be careful to possible interruptions occuring in the middle of the delay function.