AVR Embedded Tutorial - Delays: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: AVR Embedded Tutorial - Delays
| Old | New | Line | |
|---|---|---|---|
| 1 | + | ## Delays for ATmega328 / Arduino | |
| 2 | + | ||
| 3 | + | ... and of course other AVR controllers. | |
| 4 | + | ||
| 5 | + | Accurate timing on the AVR controllers is actually very simple - if you do it in assembler. Simple loops in Pascal, on the other hand, cannot be precisely timed, because you never know how the compiler will build the loop next time. | |
| 6 | + | ||
| 7 | + | For example, with compiler option -o1, a for loop with a 16bit counter variable is created, the same loop with -o2 and -o3 with 8 bit. This makes the loop almost twice as fast. | |
| 8 | + | ||
| 9 | + | ## Short delays in the microsecond range | |
| 10 | + | ||
| 11 | + | ``` pascal | |
| 12 | + | {$ goto on} // must be specified | |
| 13 | + | ||
| 14 | + | procedure delay_short(); | |
| 15 | + | label | |
| 16 | + | loop; | |
| 17 | + | begin | |
| 18 | + | asm | |
| 19 | + | ldi r16, 60 | |
| 20 | + | loop: | |
| 21 | + | nop | |
| 22 | + | dec r16 | |
| 23 | + | brne loop | |
| 24 | + | end ['r16']; | |
| 25 | + | end; | |
| 26 | + | ``` | |
| 27 | + | ||
| 28 | + | You have to try out the size of the counter variable. The loop lasts 4 clock cycles, so at 8MHz 2 loops would be one microsecond. In addition, there is a jump into the routine and the compiler tinkers with some stack pointer and register backup. | |
| 29 | + | ||
| 30 | + | ## Longer delays in the millisecond range | |
| 31 | + | ||
| 32 | + | ``` pascal | |
| 33 | + | {$ goto on} // must be specified | |
| 34 | + | ||
| 35 | + | // pause msec, 1 to 255 msec | |
| 36 | + | ||
| 37 | + | procedure delay_ms(time: uint8); | |
| 38 | + | const | |
| 39 | + | fmul = 1 * fcpu div 1000000; | |
| 40 | + | label | |
| 41 | + | loop1, loop2, loop3; | |
| 42 | + | begin | |
| 43 | + | asm | |
| 44 | + | ldd r20, time | |
| 45 | + | loop1: | |
| 46 | + | ldi r21, fmul | |
| 47 | + | loop2: // 1000 * fmul = 1000 * 1 * 8 = 8000 cycles / 8MHz | |
| 48 | + | idi r22, 250 | |
| 49 | + | loop3: // 4 * 250 = 1000 cycles | |
| 50 | + | nop | |
| 51 | + | dec r22 | |
| 52 | + | brne loop3 | |
| 53 | + | dec r21 | |
| 54 | + | brne loop2 | |
| 55 | + | dec r20 | |
| 56 | + | brne loop1 | |
| 57 | + | end ['r20', 'r21', 'r22']; | |
| 58 | + | end; | |
| 59 | + | ``` | |
| 60 | + | ||
| 61 | + | With this loop you get pretty accurate timing in the range 1 to 255msec. The loop may be interrupted by interrupts and then, of course, it will take longer. | |
| 62 | + | ||
| 63 | + | The inner loop lasts 4 clock cycles per run, ergo 1000 cycles. The middle loop makes it 1msec depending on the clock frequency (1 pass at 1Mhz, 8 passes at 8MHz, 16 passes at 16MHz). The outer loop then corresponds to the number of milliseconds. | |
| 64 | + | ||
| 65 | + | **Caution!** fmul, fcpu must be constants. Then the compiler calculates the value when compiling and uses it permanently. The compiler would insert an integer division as variables and you don't really want that - in addition, the assignment ldi to a variable goes wrong. | |
| 66 | + | ||
| 67 | + | ## Even longer delays | |
| 68 | + | ||
| 69 | + | ... in seconds? Really, it doesn't have to be that way. Already 50msec can be taken at startup when the controller still has to wait for the peripherals. But long delays in the program flow are bad style and there are always better options. | |
| 70 | + | ||
| 71 | + | ## See also | |
| 72 | + | ||
| 73 | + | - [[AVR Embedded Tutorial|AVR Embedded Tutorials]] - Overview page | |
| 74 | + | ||
| 75 | + | --- | |
| 76 | + | *From the Free Pascal wiki, page "AVR Embedded Tutorial - Delays", as it stood on 2021-12-05 after a change by Ccrause, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 77 | + | Category: AVR | |
| 78 | + | Category: Arduino | |
| 79 | + | Category: Embedded | |
| 80 | + | Category: Tutorials |
