Un ciclo di ritardo è utile quando si vuole "sospendere" o "ritardare" l'esecuzione di un programma per un certo tempo noto (ad esempio volendo accendere un LED e poi spegnerlo dopo un tempo prefissato). Un semplice esempio di ciclo di ritardo è il seguente:
Per calcolare il tempo di ritardo prodotto dal precedente ciclo bisogna ricordarsi che le istruzioni di salto richiedono 1 ciclo macchina (4 periodi di clock) quando non viene effettuato il salto e 2 cicli macchina (8 periodi di clock) quando il salto viene effettuato. Considerando per esempio un clock a 4 MHz, i tempi precedenti sono uguali rispettivamente a 1µs e a 2µs.
Il ciclo precedente viene ripetuto 167 volte e ad ogni ripetizione, tranne l'ultima, DECFSZ non produce alcun salto, mentre GOTO salta sempre: dunque per 166 volte il tempo di esecuzione del ciclo è di 3µs (TDECFSZ/NO_JUMP + TGOTO = 1µs + 2µs = 3µs). Durante l'ultima ripetizione DECFSZ salta mentre GOTO non viene eseguita: dunque il tempo di esecuzione è di 2µs (TDECFSZ/JUMP).
Pertanto il tempo totale di ritardo dovuto all'esecuzione del cicloè dato da:
166 x 3µs + 1 x 2µs = 500 µs
Siccome il massimo valore che può essere caricato in un registro a 8 bit è 255 (FF), con questo tipo di cicli il ritardo massimo è inferiore al millisecondo (con un clock a 4MHz - chiaramente variando la frequenza di clock, cambia anche il tempo di ritardo generato).
Per ottenere ritardi più lunghi occorre aggiungere istruzioni (es. NOP) all'interno del ciclo oppure usare cicli nidificati. Si consideri il seguente esempio:
Accanto a ogni istruzione è indicato il tempo di esecuzione (nell'ipotesi di utilizzare un clock a 4 MHz e considerando, per le istruzioni di salto, il tempo di esecuzione del solo caso più frequente). Il ciclo più esterno LOOP1 viene eseguito 4 volte. All'interno di LOOP1 troviamo LOOP2 (che viene eseguito 255 volte) e LOOP3 (anch'esso eseguito 255 volte).
Il tempo di esecuzione totale (tralasciando, per le istruzioni di salto, di considerare il tempo differente dell'ultima esecuzione) è dato da:
CICLO INTERNO LOOP3:
4 x 255 x 245 x 4µs = 0,9996s
CICLO INTERMEDIO
4 x 255 x 5µs = 5,1ms
CICLO ESTERNO
4 x 5µs = 20µs
TEMPO TOTALE = 0,999gs + 5,1ms + 20µs = 1,00472s
Si osservi che il tempo di esecuzione di una singola ripetizione del ciclo interno è di 4µs, mentre gli altri due cicli hanno un tempo di 5µs. La ragione è che nei cicli esterni vengono eseguite anche le due istruzioni MOVLW e MOVWF per l'inizializzazione dei contatori, mentre nel ciclo interno viene eseguita la NOP.
Per approfondire l'argomento, consigliamo di leggere questa guida, che contiene anche il link a un comodo generatore automatico di cicli di ritardo per il PIC.
ATTENZIONE:
Il codice prodotto dal generatore automatico di cicli di ritardo non funziona se non viene attribuito un indirizzo base alla direttiva cblock iniziale. Per esempio
cblock d1 d2 d3 endc
va corretto inserendo un indirizzo (nell'area di RAM dedicata ai registri General Purpose), per esempio:
cblock 0x20 d1 d2 d3 endc
Sito realizzato in base al
template offerto da
http://www.graphixmania.it