Una macro per la generazione di ritardi di estrema precisione con Atmel AVR

La macro _Waiste_us il cui codice  sorgente è riportato nel listato 1, consente di generare con precisione  un   ritardo   da   un   minimo   di 1000000/F_CPU (F_CPU è la frequenza in Hz a cui  lavora  il  micro)  fino  ad  un  massimo  di 25.769.803.779/F_CPU_in_MHz.

;******************************************************************************
     .equ F_CPU = 3579545 ;Hz

.Macro _Waiste_us ;n
     .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
Listato 1

Per utilizzare la macro  è sufficiente  chiamarla passandogli come parametro un intero che costituisce il tempo di ritardo espresso in microsecondi. La precisione è pari all’inverso della frequenza del clock e la macro occupa un massimo di  13  words  di  codice.  Prima  di  utilizzare la macro è necessario inizializzare la costante F_CPU assegnandoli il valore della frequenza della CPU espressa in Hz.

 

 

STAMPA     Tags:, , ,

2 Commenti

  1. Maurizio Di Paolo Emilio Maurizio 5 novembre 2016
  2. Fausto 8 novembre 2016

Scrivi un commento

ESPertino è la nuova scheda per IoT compatibile ARDUINO.
Scopri come averla GRATIS!