STM32 Delay Microsecond Millisecond Utility | DWT Delay & Timer Delay

Previous Tutorial Previous Tutorial Tutorial 18 Next Tutorial Next Tutorial
STM32 Delay Microsecond & Millisecond Utility | DWT Delay & Timer Delay
STM32 Course Home Page 🏠


STM32 Timer Delay Example Using Timer And DWT Delay us ms Tutorial


In this tutorial, I’ll show you a couple of methods to implement STM32 delay functions both in microseconds and milliseconds. We’ve seen the HAL_Delay() utility in the built-in HAL libraries by STMicroelectronics. But it can only give you milliseconds delay, and that’s the goal for this tutorial. We’ll be using the DWT and STM32 hardware Timers for our implementations.


   Required Components For LABs   


All the example code/LABs/projects in the course are going to be done using those boards below.

QTY Component Name 🛒 🛒
2 BreadBoard Amazon eBay
1 LEDs Kit Amazon Amazon eBay
1 Resistors Kit Amazon Amazon eBay
1 Capacitors Kit Amazon Amazon eBay & eBay
2 Jumper Wires Pack Amazon Amazon eBay & eBay
1 9v Battery or DC Power Supply Amazon Amazon Amazon eBay
1 Micro USB Cable Amazon eBay
1 Push Buttons Amazon Amazon eBay
1 USB-TTL Converter or FTDI Chip Amazon Amazon eBay  eBay

★ Check The Full Course Complete Kit List

Some Extremely Useful Test Equipment For Troubleshooting:

Affiliate Disclosure: When you click on links in this section and make a purchase, this can result in this site earning a commission. Affiliate programs and affiliations include, but are not limited to, the eBay Partner Network (EPN) and

   STM32 Delay Functions   


In earlier tutorials, we’ve been using the HAL_Delay utility function to get milliseconds time delay. And as we’ve discussed it’s built on the SysTick timer that ticks at a rate of 1000Hz and can only give you multiples of 1ms time delay. Using time delays despite being a bad practice to though out everywhere in the code, it can be mandatory in many cases and can be justified.

In OS-based applications, it’s forbidden to use time delays as it will mess up the timing behavior of the system. But a few microseconds of delay in a function that sends a trigger pulse to an ultrasonic sensor, LCD, or whatever can be justified and adds no risk to the system timing.

In the upcoming tutorials for interfacing various modules and actuators, we’ll pay attention to the blocking nature of code built with delays and maybe duplicate the work in order to have both versions for a driver that works in blocking and non-blocking mode. Blocking functions will use the delay utility which we’ll develop today. And the non-blocking functions will be handled by the SysTick timer as we’ll learn in the future.

For this tutorial, let’s only focus on how to generate time delays in us and ms with high accuracy. We’ll discuss a couple of ways to achieve this. First of which is the WDT, and the second one is the hardware timer modules.


   STM32 DWT Delay   


As we’ve discussed in an earlier tutorial, STM32 Debugging, the ARM Cortex®-M3/M4 core contains hardware extensions for advanced debugging features. The debug extensions allow the core to be stopped either on a given instruction fetch (breakpoint) or data access (watchpoint). The Arm® Cortex®-M3/M4 core provides integrated on-chip debug support. It is comprised of:

  • SWJ-DP: Serial wire / JTAG debug port
  • AHP-AP: AHB access port
  • ITM: Instrumentation trace macrocell
  • FPB: Flash patch breakpoint
  • DWT: Data watchpoint trigger
  • TPUI: Trace port unit interface (available on larger packages, where the corresponding pins are mapped)
  • ETM: Embedded Trace Macrocell (available on larger packages, where the corresponding pins are mapped)

We are interested in the Data Watchpoint Trigger which provides some means to give some profiling information. For this, some counters are accessible to give the number of:

  • Clock cycle
  • Folded instructions
  • Load store unit (LSU) operations
  • Sleep cycles
  • CPI (clock per instructions)
  • Interrupt overhead

By tracking the clock cycles, we can generate an accurate time delay given that the operating frequency of the CPU is known or can be known. To make the code more generic, we’ll read the core speed from the RCC while initialization and use it for further work.

DWT_Initialization() Function

DWT_Delay_us() Function

DWT_Delay_ms() Function


   STM32 Hardware Timer Delay   


An alternative way for the DWT to achieve time delay in milliseconds, microseconds, and even nanoseconds (require SysCLK >= 100MHz) is the hardware timers in the microcontroller. You can use one of them to achieve this task. I prefer to use a general-purpose or basic timer so you don’t lose valuable hardware resources for this task. For this tutorial, I’ll be using TIMER4 which is a general-purpose timer and connected to the APB1 bus. Here is the microcontroller’s architecture diagram.

While configuring the clock tree make sure to clock the required timer @ the Fsys clock as it’s assumed in the code that the timer clock is the same as the CPU. You can change the configurations, the clock, even the timer itself, and the bus by adjusting a couple of lines in code.

The timer Prescaler is set up depending on the Fsys clock so that each timer tick accounts for a 1-microsecond time unit. This information is stored in a static global variable in the code file and you don’t have to manually figure anything out. Jut initialize the timer delay function and you’re good to go. If another timer to be used for this task, you’ll only have to change this line down below.

TimerDelay_Initialization() Function

TimerDelay_us() Function

TimerDelay_ms() Function


   STM32 Delay Microsecond & Millisecond Utility    


All the delay functions with both methods WDT and Timer are found in the util folder that you’ll download from the link below. It includes both the source code and header file for each WDT_Delay and TimerDealy.

In the LAB down below, I’ll show you how to add this to your project directory, include it in your application, and test it using an output GPIO pin and measure the timing with a digital storage oscilloscope (DSO).

Download The Util Folder

STM32 Timer Delay Example Using Timer And DWT

   STM32 Delay us & ms Example LAB   


LAB Number 15
LAB Title STM32 Delay us and ms with WDT or Timer module
  • Set up a new project as usual with a GPIO output pin for testing
  • Add the util to our project directory
  • include the delay utilities (timer or DWT) and test it


   STM32 Delay Example LAB15   


And now, let’s build this system step-by-step


Step1: Open CubeMX & Create New Project

Step2: Choose The Target MCU & Double-Click Its Name

Step3: Configure A0 pin to be a GPIO output pin

Step4: Select the timer you’re willing to use for the delay. Let it be TIMER4, just enable the clock

No other configuration for the timer is needed. It’s all done in the code. However, don’t forget to remove the HAL_TIM_Config() from the main.c code as you won’t use it.

STM32 Timer Delay Example Using Timer And DWT Delay us ms functions cubemx

Step5: Set The RCC External Clock Source

STM32 RCC External Clock Selection CubeMX

Step6: Go To The Clock Configuration

Step7: Set The System Clock To Be 72MHz

Step8: Name & Generate The Project Initialization Code For CubeIDE or The IDE You’re Using

Step9: Add The util directory & add it to the path as a source code directory

Copy the util folder that you’ve downloaded earlier

Open the project in CubeIDE and right-click the project name and click paste

STM32 Timer Delay Example Using Timer And DWT Delay us ms

The folder will be added to your project. However, it’s not considered as a source code directory, so it won’t be compiled and give you linking error in the linking stage if you call any of its functions.

STM32 Timer Delay Example Using Timer And DWT Delay us ms functions

Right-click the util folder and click properties. And navigate to C/C++ paths and symbols, and source locations tab.

STM32 Timer Delay Example us and ms Functions

In the source locations tab, click add folder and add our util folder.

STM32 Timer Delay Example Using Timer And DWT Delay

STM32 Timer Delay Example Using Timer And DWT Delay Tutorial

That’s it, now it’s properly added to our project and can be included in the application code (in main.c).

Can you notice that little icon changes in the util folder? this indicates that the IDE knows that this is a source code directory. It wasn’t like that when we first added it.

STM32 Timer Delay Example Using Timer And DWT Delay us ms function

Step10: The Last step is to remove the timer config function from the main.c file & make sure to name the timer instance correctly in the TimerDelay.c file


Here is The Application Code For This LAB

Note that the hal_timer_config function is removed and never called. The timer initialization is now done in the TimerDelay_Init() routine.

Or you can delay with the WDT as in the following application

Download The Timer & DWT Delay LAB15 Project


The Result For LAB Testing

Here are some screenshots from my DSO showing the timing for various signals. 1uSec, 10uSec, 100uSec, 1mSec delays. And how accurate it actually is. The DWT delay has shown similar results to the timer functions, they are nearly identical. However, the timer delay is much accurate at the low-end very short 1uSec delay. But all in all, it’s as good as it can be.

STM32 Delay Microsecond Millisecond Timer Delay DWT Delay - 1uSec

STM32 Delay Microsecond Millisecond Timer Delay DWT Delay - 10uSec

STM32 Delay Microsecond Millisecond Timer Delay DWT Delay - 100uSec

STM32 Delay Microsecond Millisecond Timer Delay DWT Delay - 1mSec



Stay tuned for the upcoming tutorials and don’t forget to SHARE these tutorials. And consider SUPPORTING this work to keep publishing free content just like this!


Previous Tutorial Previous Tutorial Tutorial 18 Next Tutorial Next Tutorial


Share This Page With Your Network!
Join Our +25,000 Newsletter Subscribers!

Stay Updated With All New Content Releases. You Also Get Occasional FREE Coupon Codes For Courses & Other Stuff!

Photo of author
Khaled Magdy
Embedded systems engineer with several years of experience in embedded software and hardware design. I work as an embedded SW engineer in the Automotive & e-Mobility industry. However, I still do Hardware design and SW development for DSP, Control Systems, Robotics, AI/ML, and other fields I'm passionate about.
I love reading, writing, creating projects, and teaching. A reader by day and a writer by night, it's my lifestyle. I believe that the combination of brilliant minds, bold ideas, and a complete disregard for what is possible, can and will change the world! I will be there when it happens, will you?

6 thoughts on “STM32 Delay Microsecond Millisecond Utility | DWT Delay & Timer Delay”

  1. Hello Mr.Magdy
    your tutorials on STM32 as far as I know are the most diverse and thorough tutorials I could found however it could be a bit more noob friendly(as someone who has started learning microcontrollers from stm32 not Arduino or PIC)

    now the question is how do we create several pulse trains with 1us resolution in the background without interfering with while() loop?
    let’s say we need 10 pulse channels
    one of them is carrier so the others are with respect to the first one and we can vary the delay and pulse width of them on the fly
    but they all operate in the background without consuming much processing power
    so we can write other stuff in the while() loop

    • If i got your question right, then I think you can operate the PWM module in synchronized mode so that you have one master channel and the others will be in sync with its timing. Independent edge mode will also enable you to add any time shift in any channel and vary its duty cycle on the run.

Comments are closed.