Precise delay with counter

If you work at high speed, as STM32F4 devices do (84MHz or more) then this tutorial is not right for you. But, you are able to descrease system speed to any frequency basicly you want.

If you want to use delay with systick down timer, look at my library here.

You can use great solution, Systick timer to make an interrups for you. But you can also decrease speed to let’s say 42Mhz, and that systick every 42ticks checks for variable in interrupt handler and increase/decrease it if neccessary, that can take up to 10cycles. In practise, that’s the same if we have 32MHz clock instead of 42MHz.

I was making some experiments with delay functions with only one variable (counter) and delay in simple way like

but this method is not accuracy, because this works with system ticks and depends on core clock. But how we can make a delay like this, to be independent of core clock?

This can be done, of course. We need to make some mathematics at the beginning and then we are ready.

First, we have to know, how many ticks our while loop actually  takes. I create a simple program with while loop inside, and start debugger. I got result, that while loop “while (variable–);” takes exactly 4 clock cycles. We are getting closer.

Let’s say, our system clock is 180000000 Hz (STM32F429 Discovery). If we want to make a simple 1us delay, then we have to count 180 ticks to get this. If one while loop takes 4 cycles, then we have to divide our counter by 4.

This will be great, if we are making this inside program. But, calculating takes some time (with floating point unit activated only 1 cycle), then calling function and returning back also takes some time. My debugger says that I have to always substract 10cycles. I make some tests with different delay numbers and results are below.

Test code:

In example above is delay fixed to 1000us (1ms), but I tried different values. I made test on STM32F429 Discovery board (180MHz), FPU activated.

Delay I wanted Ticks I got @ 180MHz Ticks I got @ 168MHz Ticks I got @ 84MHz
50us 9010 8410 4210
125us 22510 21010 10510
250us 45010 42010 21010
1000us 180010 168010 84010

So, always is “xxx10” at the end. If we assume that this is because of function calls and calculating, we can say that our equation is very simple. If we substract 10 from result, and divide that by number of delay we want, then we will see that we get exactly our system clock in MHz.

To calculate proper ticks for our delay, we first have to get ticks from device. This can be simply done with RCC_GetClocksFreq in CMSIS libraries.

In function below, we divide with 4M. That’s because 4 is from while loop takes 4cycles and if we want to get 1us, we have to divide with 1M. This multiplier we use then in our pre calculations for delay.

That’s all. We are ready to make an example. I put it to oscilloscope and results were really great.

For that example, my DISCO library will be great for you. Download below.

tilz0R

Owner of this site. Application engineer, currently employed by STMicroelectronics. Exploring latest technologies and owner of different libraries posted on Github.

You may also like...