Full Version : Delays in AVR ASM
avr >>ASSMBLER ROUTINES >>Delays in AVR ASM


AVR_Admin- 05-13-2006
Delay Routines by Jan Huygh of Brussels

CODE

;******************************************************************************
;_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 )
;

;******************************************************************************
;The CPU-speed needs to be set before you can use _Waiste_us.
;Find your CPU-speed in the list here below and uncomment it (remove the ";")
;then press Ctrl^S to save to disk otherwise the include file used by AVR studio
;will be the unchanged version on your disk.
;
;              
; .equ F_CPU =  1000000;Hz
; .equ F_CPU =  2000000;Hz
.equ F_CPU =  3579545;Hz
; .equ F_CPU =  3686400;Hz
; .equ F_CPU =  4000000;Hz
; .equ F_CPU =  4032000;Hz
; .equ F_CPU =  4096000;Hz
; .equ F_CPU =  4194304;Hz
; .equ F_CPU =  4433619;Hz
; .equ F_CPU =  4915200;Hz
; .equ F_CPU =  5000000;Hz
; .equ F_CPU =  5068800;Hz
; .equ F_CPU =  5990400;Hz
; .equ F_CPU =  6000000;Hz
; .equ F_CPU =  6144000;Hz
; .equ F_CPU =  6500000;Hz
; .equ F_CPU =  7372800;Hz
; .equ F_CPU =  7680000;Hz
; .equ F_CPU =  8000000;Hz
; .equ F_CPU =  9000000;Hz
; .equ F_CPU =  9216000;Hz
; .equ F_CPU =  9830400;Hz
; .equ F_CPU = 10000000;Hz
; .equ F_CPU = 10240000;Hz
; .equ F_CPU = 11000000;Hz
; .equ F_CPU = 11059200;Hz
; .equ F_CPU = 11520000;Hz
; .equ F_CPU = 12000000;Hz
; .equ F_CPU = 12000393;Hz
; .equ F_CPU = 12288000;Hz
; .equ F_CPU = 13500000;Hz
; .equ F_CPU = 14318180;Hz
; .equ F_CPU = 14745600;Hz
; .equ F_CPU = 15000000;Hz
; .equ F_CPU = 15360000;Hz
; .equ F_CPU = 16000000;Hz
; .equ F_CPU = 16000312;Hz
; .equ F_CPU = 16257000;Hz
; .equ F_CPU = 16384000;Hz
; .equ F_CPU = 17734475;Hz
; .equ F_CPU = 18000000;Hz
; .equ F_CPU = 18432000;Hz
; .equ F_CPU = 19660800;Hz
; .equ F_CPU = 20000000;Hz


.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

.macro _Cycle_Waister
.If @0 == 1
 nop
.EndIf
.If @0 == 2
 nop
 nop
.EndIf
.If ((@0 > 2) && (@0 < 769))
;C=3n
;769=(3 * (2^8)) + 1
 .set Loops_Needed = @0/3
 ldi  R16,Low(Loops_Needed)
     Loop:
   dec  R16
 brne Loop
 .set Cycles_Left_To_Do = @0 - (3*Loops_Needed)
 _Cycle_Waister Cycles_Left_To_Do
.EndIf
.If (@0 > 768) && (@0 < 262146)
;C=1+4n
;262146 = 1 + (4 * 2^16) + 1
 .set Loops_Needed = (@0 - 1)/4
 ldi  ZL,Low(Loops_Needed)
 ldi  ZH,High(Loops_Needed)
     Loop:
   sbiw ZL,1
 brne Loop
 .set Cycles_Left_To_Do = (@0 - (4*Loops_Needed))-1
 _Cycle_Waister Cycles_Left_To_Do
.EndIf
.If (@0 > 262145) && (@0 < 83886083)
;C=2+5n
;83.886.083 = 2 + (5 * 2^24) +1
 .set Loops_Needed = (@0 - 2)/5
 ldi  R16,Low(Loops_Needed)
 ldi  ZL,Byte2(Loops_Needed)
 ldi  ZH,Byte3(Loops_Needed)
     Loop:
   subi R16,1
 sbci ZL,0
 sbci ZH,0
 brne Loop
 .set Cycles_Left_To_Do = (@0 - (5*Loops_Needed))-2
 _Cycle_Waister Cycles_Left_To_Do
.EndIf
.If (@0 > 83886082) && (@0 < 25769803780)
;C=3+6n
;25769803780 = 3 + (6 * 2^32) +1
 .set Loops_Needed = (@0 - 3)6
 ldi  XL,Low(Loops_Needed)
 ldi  XH,Byte2(Loops_Needed)
 ldi  ZL,Byte3(Loops_Needed)
 ldi  ZH,Byte4(Loops_Needed)
     Loop:
    sbiw Xl
 sbci ZL,0
 sbci ZH,0
 brne Loop
 .set Cycles_Left_To_Do = (@0 - (6*Loops_Needed)) - 3
 _Cycle_Waister Cycles_Left_To_Do
.endif
.endmacro


Link: http://www.avrfreaks.net/modules/FreaksFil...685/_Delays.asm























Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.