The easiest way to get started with a processor is writing a small program to blink a led. This can be done with some easy lines, switch the led on, delay 1 second, switch the led off, delay 1 second, and loop that forever.
Some starter-friendly processor like Arduino (well, technically, AVR) comes with an already-made, easy to use delay function, which is part of the friendly Arduino IDE. But, for example, the STM32 family does not have those luxuries built-in.
When I was new to the STM32 family, I was very frustrated every time I need a delay function. And recently, when I need a sub-millisecond delay function, I need to delay some microseconds, it took me quite some time to find an effective way to have one. So, I set out to compose a delay library, with all the delay functions I would ever need.
I take no credit for these codes. Some of them, I wrote them myself. But some, I take the ideas from various sources on the internet. Just like the writers of those code, who share them freely and publicly, I share my delay library here with the hope that someone will find it useful, that it would saves someone time when he look for these functions. You can use these in whatever way you want.
Remember to include the right "stm32fxxx.h" file in the "delay.h". Now, some quick words about the functions.
I configure SysTick Timer to trigger an interrupt every millisecond. Remember to call "SysTick_Init()" in your config code (before the main loop). From my experience, it is highly recommended to leave your SysTick Timer at 1kHz (1 trigger per ms). Having SysTick interrupt every 1 us could literally grind your processor to a halt. The interrupt handler "SysTick_Handler" is also in the file "delay.c".
"delay_ms(n)" and "delay_us(n)" are self-explained. AFAIK, the most effective way to delay some microseconds is to use a loop of assembly code.
Since I really like Arduino's "millis()" function, I get my own version here. Calling "millis()" will return the milliseconds that have passed since the SysTick Timer is configured.
And since I usually write my code to do a particular task periodically (every 100 ms, for example), I write a function called "on_period(old_millis, period_ms)". This functions will return 1 if period_ms ms have passed since old_millis, and the return value is 0 otherwise.
Example code:
1 2 3 4 5 6 7 8 9 10 | int main(void) { SysTick_Init(); while (1) { // Toggle led every 1 second toogle_led(); delay_ms(1000); } } |
Example on how to plan your periodical tasks. This is like a simple task scheduler. Your program will only run tasks at specified intervals. No wasting time sitting on delay functions doing nothing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | int main(void) { SysTick_Init(); while (1) { // Call toggle_led every 1 second toggle_led_task(1000); // Another example task which will be executed every 70 ms another_task(70); } } void toggle_led_task(uint16_t period) { // Remember that old_millis need to be static static uint32_t old_millis = 0; // old_millis will be updated if on_period return 1 if (on_period(&old_millis, period) { toggle_led(); } } |