2
\$\begingroup\$

I recently saw some people saying that configuring a timer so that it triggers an interrupt each 1us is not a good way of doing that.

Also, I assume that;

Start = TIMx.CNT;
Bla;
Bla;
Bla;
End = TIMx.CNT;

An algorithm like that will have problems in case of overflow/underflow of the counter during process.

So what is the most proper method to do so?

If needed, I am using 168MHz stm32f4 discovery board.

Thanks.

P.s : I mixed delay and time measurement because I guess they depend on the same logic so it should not be a confusion.

\$\endgroup\$

closed as too broad by Chris Stratton, Turbo J, berendi, DKNguyen, Elliot Alderson Aug 5 at 20:19

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ Other way around. You make an interrupt that triggers after a timer counts a certain number of microseconds for delay, or stops the timer for measurement. Not every trigger every microsecond. \$\endgroup\$ – DKNguyen Aug 4 at 7:14
  • 1
    \$\begingroup\$ Depends on your processor. In a 1GHz multicore (32-bit) ARM you can time a lot more accurate then a 8-bit 4MHz micro-controller. Many micro controllers have dedicated pulse width measure logic. More important: what do you need it for, what are you actually trying to achieve? \$\endgroup\$ – Oldfart Aug 4 at 7:16
  • 1
    \$\begingroup\$ @DKNguyen thanks but I cannot say I understood well, could you please ellaborate your answer or provide me an example code? \$\endgroup\$ – muyustan Aug 4 at 7:22
  • \$\begingroup\$ @Oldfart lets say 168MHz processor, and I just want to achieve a us precise delay function. Only thing to be done in ISR is incrementing a uscounter variable. \$\endgroup\$ – muyustan Aug 4 at 7:24
  • 1
    \$\begingroup\$ @muyustan For delay: If you're setting an alarm, do you set the alarm to ring every minute and count how many times the alarm as rung? Or do just set it to ring after the right number of minutes have past? For measurement: Do you watch a clock and mark down every time a minute has passed? Or do you just stop the clock when your event has stopped and read off the time? \$\endgroup\$ – DKNguyen Aug 4 at 16:28
3
\$\begingroup\$

Most delay methods in a microcontroller only guarantee that the delay will be at LEAST what you want it to be, not precisely what you want it to be.

The simplest way is to poll a timer in the main loop amongst all the other things that are running to check if the timer has exceeded a particular count.

Another way is to set a timer interrupt to trigger whenever a timer reaches a certain count. The interrupt could set a flag that some other part of the main loop checks to see if the minimum delay has been met. The simplest, precise way to do it is to get the interrupt to directly execute whatever it was you want delayed, but this is a really bad idea if what you want executed is big, long, and complicated since you spend too much time in the interrupt service routine.

But even with the interrupt directly executing your delayed task, there is variance and latency. Precise delays (or precise timing in execution) are not an MCU's strength because the MCU is doing other things. You rarely know what the MCU might be doing when an interrupt triggers so you rarely know how much time it takes for the MCU to put everything else aside and get around to the interrupt.

Getting a PRECISE delay time is probably not feasible since it would take a lot of careful coding and verification of the entire program, and as soon as any part of the program changes, that precise delay may no longer exist. Timing precision of execution is not an MCU's strength and a lot of work goes into just getting an MCU to execute everything it needs to before it's deadline (like real-time systems or an RTOS), let alone getting something to execute exactly when you want it to.

You should find a better way to do whatever it is you are trying to do, but you have not told us what you are trying to do. One of the main reasons an MCU has hardware peripherals is because an MCU is bad at precise timing. A lot of peripherals (like timers) are intended to take care of that so that the MCU doesn't have to. But if you truly need something complex to happen with precise timing, an MCU won't do the job without special hardware.

\$\endgroup\$
  • \$\begingroup\$ That was explanatory, thanks. \$\endgroup\$ – muyustan Aug 5 at 2:49
4
\$\begingroup\$

You can't really combine delays and measurements into one case. There is no common logic or one proper method. It depends on what you are doing and what timers and features the microcontroller has. A more specific answer would require a more specific question.

If you implement measuring how long a piece of code executes like in your code, as long as the execution time is less than timer overflow period, there really is no problem if timer wraps around during the timing. If end time is 0x0000 and start time is 0xFFFF, 16-bit math still says it's 1 tick.

If you just want a blocking delay, start a timer and wait until count has reached end by looking at overflow/underflow flags depending on which way the timer counts.

If you have a timer and must measure timing of external signals, you can use the timer capture mode to get timestamps of signal transitions.

\$\endgroup\$
  • \$\begingroup\$ Thanks, but your offering to make a special us delay is as follows, first configure a timer so that it counts in 1 MHz. Then in the delay function start the timer, use a dummy while loop to iterate until TIMx.CNT<desiredDelayTime and then stop the timer again. Correct? \$\endgroup\$ – muyustan Aug 4 at 15:24
  • \$\begingroup\$ No that is one of the worst way to do it if you want accurate. If the timer runs at 1us rate, it will be hard to go for 1us accuracy, if you are not careful you can end up with zero delay or 2 us delay or other error. Much better would be to use 168 MHz timer and make it count 168 ticks. But usually this is overkill. Please describe what is it that you are doing that needs 1us accurate delays, if it is delays you need in the first place. \$\endgroup\$ – Justme Aug 4 at 15:55
  • \$\begingroup\$ I started to think that I cannot express myself, what I want to do is generate my own us presice delay function that I can use at anywhere in my program/code, or simply the microseconds equivalent of HAL_Delay(). \$\endgroup\$ – muyustan Aug 4 at 16:54
  • \$\begingroup\$ @muyustan if that is all you want then what is wrong with a function that has a simple for loop that runs n times the microseconds you want doing nothing? The constant n needs to be fine tuned to run for exactly the amount you want. \$\endgroup\$ – Justme Aug 4 at 17:10
  • \$\begingroup\$ so to do this, should I first examine how long an empty for loop takes on my cpu? A proposal to do that? And if it is the case, then why a company like ST ( such an experienced team with these stuff) uses a SysTick timer and interrupt for each 1 ms for its HAL library delay function? Thanks anyway for your helps. \$\endgroup\$ – muyustan Aug 4 at 17:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.