INCLUDE "_Delays.asm" enables you to use the following macro in your code
_Waiste_us n (with n = 1 to 25.769.803.779)
This macro will generate a wait loop from 1 µs to 25.769.803.779 µs.
_Waiste_us is actually limited to minimum (1.000.000/F_CPU) us because we can not loop for less then 1 instruction cycle. If you request a delay below this limit _Waiste_us will insert no instruction in your code.
_Waiste_us is absolutely exact down to (1/Your_CPU_frequency_in_MHz) µs
_Waiste_us will pick the smallest code for your delay (1 to 13 words). Well that is not 100% true. It will pick the shortest usable loop 8-,16-,24- or 32-bit and add a 2nd 8-bit loop and maybe 2 NOP's to match exactly the delay you requested. In some cases that results in code that is 1 word longer than the minimum code that would have generated the requested delay. (Fixing that would make the macro really complex and I decided the benefit was not worth the effort)
A-men
;****************************************************************************** ;_Delays.asm Version 0.0a ;****************************************************************************** ; ;Written for : Atmel "AVR Assembler" and "AVR Assembler 2" ; when : 2005 November 20 ; where: BRUSSELS - BELGIUM - EUROPE ; who : Jan Huygh ; E-mail: jan.huygh@skynet.be
;****************************************************************************** ;A WORD FROM THE AUTHOR : ; ;I would find it motivating to find out that people use this code. ; ;On regular base (every 10 to 12 weeks) I gather the comments on the code I ;posted and use the comments to improve my code. If you have constructive ;comment then let me know. ; * Give me an evaluation. ; * Send me a mail (jan.huygh@skynet.be) subject "I use your _Delays.asm". ; * Send me a mail (jan.huygh@skynet.be) subject "Comment on your _Delays.asm"
;****************************************************************************** ;ABOUT VERSION 0.0a ; ;This is the first posted version. ; ; KNOWN BUGS : ; * None so far ; OPPORTUNITIES FOR IMPROVEMENT : ; * a version that can be used as a subroutine taking in to acount the time ; for the call and for the return. ; * a version that takes the input from the stack so it can take a variable ; for the input. ; * a version that is less precise but takes less bytes of program memory ;
;****************************************************************************** ;.INCLUDE "_Delays.asm" enables you to use the following macro in your code ; ; _Waiste_us n ; With (1.000.000/F_CPU) <= n <= 25769803779/Your_CPU_frequency_in_MHz ; ; This macro will generate a wait loop from 1 µs to 25.769.803.779 µs ; Depending on the CPU-speed set in F_CPU here below you will need to ; respect a minimum value for n. (n_minimum) = 1.000.000/F_CPU). ; This is needed because we can not loop for less then 1 ; instruction cycle. ; 25.769.803.779 µs, that's over 3h30 when you use a CPU running at 20 MHz. ; _Waiste_us is absolutely exact down to (1/Your_CPU_frequency_in_MHz) µs ; _Waiste_us will pick the smallest code for your delay (Maximum 13 words)
;****************************************************************************** ;How to use this in your code : ; ; A) Pick the correct ".equ F_CPU = x" statement ; AND ; save this file to your disk ; ; B) Make sure it is in the same folder as the other files of your current project ; OR ; Make sure the folder where you saved this file is referenced in the ; assembler options (Project=>Assembler Options=>Additional include path) ; ; C) Include the statement .INCLUDE "_Delays.asm" at the top of your program ; ; D) Use the statement _Waiste_us n, in your code ; ;Here is a code example : ; ; .INCLUDE "_Waiste.asm" ;Make the macro _Waiste_us n available in your code ; _Waiste_us 100 ;loop for 100 µs (that's 0,1 ms) ; _Waiste_us 16000 ;loop for 16.000 µs (that's 16 ms) ; _Waiste_us 7000000 ;loop for 7.000.000 µs (that's 7 s ) ;
.Macro _Waiste_us ;n ; Calculate the number of CPU-cycles needed to generate the requested delay ; taking in to account the frequency you are using for your CPU. ; You can simplify the next 9 lines of code before "_Cycle_Waister Cycles_Needed" ; to "Cycles_Needed = @0 * F_CPU / 1000000". If you do so _Waist_us will ; generate the exact delay you requested or the delay obtained by executing the ; number of cpu-cycles that brings just less then the delay you requested. ; This might be a good option if you need a certain delay but need to be sure ; you never have a delay that is even a fraction of a CPU-cycle longer than the ; delay you requested. ; The 9 lines of code here below do NOT use any space in the actual program ; memory of your AVR. ; The code here below will actually pick the number of CPU-cycles needed to ; generate EXACTLY the delay you requested and when that can not be achieved ; it will select the number of cycles that generate the delay that is the best ; approximation for the delay you requested even if that is just above the ; delay you requested. .set Fraction = @0*F_CPU/1000000 ; .set Fraction = Fraction * 100 .set Fraction = @0*F_CPU/10000 - Fraction .if Fraction >= 50 .equ Cycles_Needed = (@0 * F_CPU /1000000)+1 .endif .if Fraction < 50 .equ Cycles_Needed = (@0 * F_CPU /1000000) .endif _Cycle_Waister Cycles_Needed .endmacro