Description

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, I am going to show you how to create 1 microsecond delay 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.

Setup

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 be using 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.

F103C8_BLOCK
F103C8_BLOCK

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

As shown in the picture above, first of all you have to enable 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.

HAL_TIM_Base_Start(&htim1);

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

  while (1)
  {
	  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
	  delay_us(10);
  }
100%
100%

Result

10 us delay
10 us delay
 100 us delay
100 us delay
  1000 us delay
1000 us delay
Check out the VIDEO Below

DOWNLOAD

You can buy me a coffee sensor ūüôā

download the CODE below

100%
100%
0 0 vote
Article Rating
Subscribe
Notify of
guest
17 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Iraj Alipour

Thanks for your code . it`s very good

Nagesh

Hai ,Can you help me to get HAL microsecond delay in STM32L073RZ board for one wire communication

Salvatore

Hi,
This code doesn’t work on STM32L073RZ.
The DWT (Data Watchpoint and Tracing) is only available on Cortex M3/4/7.
So, if you want a delay of 1 us, you can use a Timer or the systick.

Dmitry

Hello! I left my comment on youtube video. But this theme is a little bit old, I do not know will You answer me here or on youtube. Thank you very much. It works with stm32f4-discovery. But I have one problem with nucleo f767zi. It works when I programm by Keil and all the time after, until I power off and power on again. After that my code freezes when meet dwt_delay. I programm again – all works again. Do You have any ideas why? F767zi get clock not from ceramic crystal, it goes bypass clock source from st-link on… Read more »

Akash

Hi if I want to give decimal value like 20.2 in the actual parameter after changing from uint16_t to float of the delay function, how will the counter work

Kishore Malakar

WHY 72MHZ IS REQUIRED ? BECAUSE EVEN IF WE TAKE 4MHZ OR 8MHZ AND DIVIDE IT BY 4 AND 8 RESPECTIVELY WE GET 1 MHZ FREQUENCY .

Vivek Kumar Singh

Hi I have done as per the above post and I am using STM32F103RB Nuleo board running at 72Mhz.
But could not toggle the GPIO. The program does not come out of the delay_us() function.

Graham Gillett

Why is there only a “;” after the while statement (Delay_uS) and not a pair of curly brackets?

Menu
17
0
Would love your thoughts, please comment.x
()
x