Microsecond/Nanoseconds delay in STM32

HAL_Delay is able to provide minimum 1 ms delay, but when it comes to microseconds, there isn’t any predefined function to create 1 us delay in HAL Library. In this tutorial, we will see how to create microsecond delays in STM32. We will be using one of the Timer to do so. The process will be same for all the STM32 devices, you need to make some minor changes though.

I am using STM32F103C8 controller with CUBEIDE but as I mentioned, it will work same for other microcontrollers with any other IDE also.


This is the most important part of this process, so read this section very carefully. First of all we need to decide which Timer to use for the process. There is no special requirement, just choose any one. I will use timer 1.

As you can see in the picture below (from the datasheet), the TIM1 is connected to the APB2 clock. This is a very important piece of information, and you should know it about the timer that you are going to use.



Now, let’s start the cubeIDE, and open the clock setup tab. Here you can see that, once I set the HCLK at MAX i.e. 72MHz, the APB2 clock is also at 72MHz.

clock setup

clock setup

This means that the TIMER 1 is also running at 72MHz, as the TIM1 is connected to the APB2. Now, let’s reduce this frequency in the timer setup section.

timer setup microseconds

timer setup microseconds
  • First of all, set the clock source as internal clock.
  • Prescaler divides the Timer clock further, by the value that you input in the prescaler.
  • As we want the delay of 1 microsecond, the timer frequency must be (1/(1 us)), i.e 1 MHz. And for this reason, the prescaler value is 72.
  • Note that it’s 72-1, because the prescaler will add 1 to any value that you input there.
  • The ARR I am setting is the max value it can have.
  • Basically, the counter is going to count from 0 to this value. Every count will take 1 us. So setting this value as high as possible is the best, because this way you can have large delays also.
  • I have set it to 0xffff-1, and it is the maximum value that a 16 bit register (ARR) can have.

I have also enabled the pin PA1 as output, so that we can see the result in an oscilloscope.

Some insight into the CODE

Now, we will write a function to create this 1 us delay. Below is the one.

void delay_us (uint16_t us)
	__HAL_TIM_SET_COUNTER(&htim1,0);  // set the counter value a 0
	while (__HAL_TIM_GET_COUNTER(&htim1) < us);  // wait for the counter to reach the us input in the parameter

When the function is called with the parameter as the number of microseconds, the following operations takes place

  • The counter in the TIM1 is set to 0
  • The counter keeps counting, until the us value has been reached

As I mentioned before, each count takes 1 us, and therefore the counter will keep counting in microseconds until the input value has reached. Once it happens, the control will come out of the loop, and we have had achieved the delay.

Inside the main loop, we must start the timer, after all the peripherals are initialized.


Now, to use the required delay, all we have to do is use the function that we created above.

  while (1)


10 us delay

10 us delay
 100 us delay

100 us delay
 1000 us delay

1000 us delay

Check out the Video Below


You can help with the development by DONATING OR Just click DOWNLOAD to download the code

Notify of

Oldest Most Voted
Inline Feedbacks
View all comments

Adblocker detected! Please consider reading this notice.

We've detected that you are using AdBlock Plus or some other adblocking software which is preventing the page from fully loading.

We don't have any banner, Flash, animation, obnoxious sound, or popup ad. We do not implement these annoying types of ads!

We need money to operate the site, and almost all of it comes from our online advertising.

Please add controllerstech.com to your ad blocking whitelist or disable your adblocking software.