ELEMANIA
PIC16F690 - Cicli di ritado
Cicli di ritardo

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:

COUNT   EQU 0x30           ; associo l'etichetta COUNT al registro 0x30 del banco zero

            BANKSEL COUNT

            MOVLW 0xA7       ; carico W con il valore 167 (in decimale)
            MOVWF COUNT    ; lo memorizzo nel registro COUNT
loop
            DECFSZ COUNT,F ; decremento di uno, se non e' zero vai a "loop"
            GOTO loop

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:

CNT1 EQU 20
CNT2 EQU 21
CNT3 EQU 22

    ; inizializzazione di CNT1
    MOVLW d'4' ;1us
    MOVWF CNT1 ;1us

LOOP1:
    ; inizializzazione di CNT2
    MOVLW d'255' ;1us
    MOVWF CNT2 ;1us

LOOP2:
    ; inizializzazione di CNT3
    MOVLW d'245' ;1us
    MOVWF CNT3 ;1us

LOOP3:
    NOP ; 1µs
    DECFSZ CNT3,F ;1us
    GOTO LOOP3 ;2us

    DECFSZ CNT2,F ;1us
    GOTO LOOP2 ;2us

    DECFSZ CNT1,F ;1us 
    GOTO LOOP1 ;2us

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

precedente - successiva

Sito realizzato in base al template offerto da

http://www.graphixmania.it