_delay_ms() function

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i have used 4Mhz clock in my code also used 64 prescale
so my exact timer pulse frequency will be 4Mhz/64=62500 Hz.mow i wanna ask u i have used a timer (timer 1)for 59 seconds delay and i also used _delay_ms() function in my coading.......Can u please tell me that on what frequency will my _delay_ms()work....either 62500 hz or 4Mhz.....simply if i want to take 250 ms delay then what should i insert with in the function......

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

_delay_ms() works off the main clock, it has nothing to do with any timer, it simply wastes cpu cycles.

So unless you have a 64 clock prescaler for the entire chip and not just timer 1 you will be running at 4MHz.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

you will be running at 4MHz.

Therefore it's important that you tell this fact. That is:

#undef F_CPU
#define F_CPU 4000000UL
#include 

You are far better off using a timer for 59 seconds than a soft delay (which is susceptible to interrupts).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Like clawson and js said you it would be running in the main clock but remember you have to define F_CPU if not you´ll get a warning a probably bad timing for your delay.
Hope this helps.

Entra a www.mecatronicamexicana.blogspot... y ve lo que los estudiantes Mexicanos de Mecatronica hacen y conoce un poco más acerca de Mecatronica

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
You are far better off using a timer for 59 seconds than a soft delay (which is susceptible to interrupts).
From what I read of the OP, the 59s is done with a timer. It is the 250ms that he wants with _delay_ms().

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanx to all....
my timer pulse is 4000000/64=62500 hz.ok
now if i use timer then it will work according to 62500hz...if i have to provide a delay of 250 ms then will it ok to provide 250 in _delay_ms()...means _delay_ms()works on 1Mhz,it will not be affected by prescaled timer pulse...
Am i right dear sir?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Means u all want to say that if i want to get 250 ms delay than _delay_ms(250)will provide me exact delay......?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have two ways to delay in an AVR. Either you count machine opcodes and just keep looping to build up a number of machine cycles. Or you start a time and then wait for a certain number of timer ticks to have passed. _delay_ms() has nothing to do with tiers, it uses the first technique. Say your AVR is running at 4MHz then one cycle is 0.25us. So to delay for 250ms you just need to execute exactly 1 million machine cycles. If you use a typical:

SUB
SUBC
BRNE

loop then the two subtraction operations maybe take 1 cycle and the BRNE (when it branches) takes 2 cycles. So that loop would take 4 machines cycles. You'd therefore have to execute it 250,000 times to make the 1,000,000 cycles you need to delay for 250ms. _delay_ms() works very like this. For it to know how many times it has to go round the inner (and possibly outer) loops it needs to know the CPU spedd (F_CPU = 4000000) and the time you want to delay for _delay_ms(250). It does NOT use a timer so how you may have chosen to setup a timer (prescaler etc) has no relevance to the use of _delay_ms().

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
)will provide me exact delay......?
Not if an interrupt happens during the delay.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
_delay_ms(250)will provide me exact delay......?
Correct as long as there are no interrupts from timers, USART etc. running otherwise time spend in the ISR will be added to your 250ms.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

_delay_ms(250)will provide me exact delay......?

1. How exact? To the millisecond (i.e. +/- 500 microseconds)?

2. I am not sure about the current state of the _delay_xx() functions in avrlibc, but a few years ago there was intense discussions on their accuracy, and at that time they where definitively not accurate to the micro- and millisecond, respectively. IIRC they didn't produce shorter delays than specified, but could very well produce longer delays.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I am not sure about the current state of the _delay_xx() functions in avrlibc

Well it kind of depends on the version of compiler you use them with and whether it has __HAS_DELAY_CYCLES.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Boy, I wish I had saved the URLs to some of those long discussions circa 2010. Might hunt for them the upcoming week end..

Anyway - I'd never contemplate _delay_xx() if accurate-to-the-cycle delays are a requirement. As I recall the discussions, the intent with the _delay_xx() function never was sto cater for such a requirement.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Boy, I wish I had saved the URLs to some of those long discussions circa 2010. Might hunt for them the upcoming week end..

Make sure "bperrybap" appears in your search terms. As I understand it the implementation of _builtin_avr_delay_cycles() has rather blown any other suggested "improvement" out of the water. The delays are now as close to being cycle accurate as they can be.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey I resemble those remarks.... :)

Here is a summary from what I remember:

The earlier was sometimes very inaccurate due to how it was implemented and its rounding calculations depending on desired delay and the CPU clock frequency. The resulting delay could be off by a significant amount in either direction (too short or too long) from the requested delay.
Most of these types of problems/issues were for short delays
using delay_us().
For example, if you asked for a 1us delay on a 1Mhz processor
instead of 1us delay you got 3us and if you asked for 4us you would get 6us.

There was an early "quick fix" a few years ago to attempt to provide something better but it inadvertently broke the delay code in one AVR libC release.
(Delays were like 4 times longer then they should be)

The next release updated the code to provide as accurate a delay as possible given the CPU frequency of the MCU.
There was so much uproar over changing how the delays worked that the new code also provided many different options with respect to algorithm and rounding.

The options are controlled with defines.
The default is to round the requested delay up
to match the closest clock cycle.
This gives a delay that as close as possible to what was
requested but is guaranteed to be at least as long as requested.
Other options are:

    - __DELAY_BACKWARD_COMPATIBLE__ (for the older loop delays) - __DELAY_ROUND_DOWN__ (rounds delay down in stead of up)
    - __DELAY_ROUND_CLOSEST__ (rounds to closest cycle; up or down)

The newer cycle accurate code depends on a built in function of gcc __builtin_avr_delay_cycles() to provide the cycle delay code. If the compiler doesn't have this functions the code reverts back to the older delay loops, but since this function has existed for many years in avr-gcc,
it is very unlikely that this recent delay.h header will ever
be used with a compiler that doesn't support it.

Another advantage of the newer code (when not using the older delay loops) is that delays can be much longer than before.
The old delay_ms() maximum was like 6 seconds or so,
and the new code is like 4000+ seconds.

Basically, if you have the new there are no issues with accuracy anymore. The delays will be accurate to within a clock cycle (assuming interrupts aren't running) and if necessary you can control the rounding direction.

One final comment.
In my testing, I compared the cycle delay code generated by __builtin_avr_delay_cycles() to the code
generated by the delay_x project:
https://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=665&item_type=project

While the two eventually generate code that will delay the
same number of cycles, Han's code is better.
i.e. in many simple cases it will be slightly smaller because Han's code
used different instructions to create the same cycle delays.
Another observation is that
the avr-gcc __builtin_avr_delay_cycles() is very
aggressive about switching to loops vs inline code. A bit too aggressive.
The side effect of this is that it needs registers for the loops.
In some cases it is actually more code than doing a few more
instructions inline.
Also, in some cases it must save a register to free up a register.
In those cases where loops and register saves are needed,
not only is the code larger, but when the register
saves/restores are taken into consideration the delay
is actually slightly longer than the delay you get with Hans'
code.

The new good is very good and much better than
the earlier code based on simple loops but in some cases it isn't quite as good as Hans' delay_x code.

One of the things still missing IMO, that would be nice
to have would be some sort of millisecond delay function
that could be passed a variable.
The current delay_xx() functions trip up so many people
particularly since the functions don't provide any sort of feedback
when constants are not used.
(There is an easy way fail the link for this situation)

Maybe I'll work on proposals for those next.... :wink:

--- bill