Routine di delay su dsPIC / PIC24

Il compilatore MPLAB C30, noto per essere uno dei migliori compilatori in giro e completamente ANSI, è fornito di serie con numerose librerie. Analizziamo le funzioni per eseguire i ritardi.

Con l’Hitech-C per utilizzare le funzioni di ritardo sui PIC16 bisognava dichiarare una macro _XTAL_FREQ con il valore di frequenza espresso in hertz del cristallo utilizzato, per contro le funzioni di ritardo disponibili ( __delay_us e __delay_ms) potevano accettare unicamente una costante come argomento, per cui non era lecito scrivere una cosa del genere:

unsigned char a=200;
__delay_ms(a);

per cui, con l’Hitech-C, volendo utilizzare le routine di delay incluse con il compilatore (molto precise) era necessario scendere a questo compromesso, oppure utilizzare librerie di delay alternative più o meno precise.

Con il C30 il “problema” dei delay è stato risolto.

Innanzitutto va dichiarata una macro FCY che rappresenta la frequenza del ciclo istruzioni, che sui pic a 16 bit vale FOSC/2. Supponiamo quindi di stare utilizzando un PIC24F che gira a 32MHz. Il valore di FCY è quindi 32000000/2 = 16000000, per cui andremo a dichiarare:

#define FCY 16000000UL //Unsigned Long

Solo successivamente possiamo includere la libreria che contiene, tra le altre, le funzioni di ritardo:

#include <libpic30.h>

Bene. Ora abbiamo a disposizione 3 funzioni di ritardo:

void __delay32(unsigned long cycles);

Esegue un ritardo pari al numero di cicli istruzioni specificato. Il numero minimo di cicli di ritardo eseguibili è pari a 12, se viene immesso un numero inferiore a 12 verrà utilizzato 12. Rimanendo nel mio esempio in cui abbiamo un FCY pari a 16MHz, il tempo in cui un’istruzione viene eseguita è pari a 1/FCY = 62.5nS, per cui il minimo ritardo che possiamo avere è di 62.5nS * 12 = 750nS

void __delay_us(unsigned int time);

Facile capire che questa serve per eseguire un ritardo espresso in microsecondi. Anche in questo caso non possiamo ottenere un ritardo inferiore a 12 cicli di istruzioni.

void __delay_ms(unsigned int time);

Ritardo in millisecondi, nessun limite minimo.

Entrambe le ultime due funzioni di ritardo convertono il valore passato come argomento per poter poi richiamare la __delay32.

Le routine sono abbastanza precise. Scrivendo un semplice programma che contiene il classico led lampeggiante:

int a=10;
while (1)
   {
   LED=1;
   __delay_ms(a);
   LED=0;
   __delay_ms(a);
   }

andando a variare il valore del ritardo e controllando con l’oscilloscopio ho i seguenti risultati:

Ritardo di 1uS (periodo: 2μS, frequenza: 500KHz)

Viene prodotto un ritardo di 1.24μS (errore relativo del +24%):

Ritardo di 10μS (periodo: 20μS, frequenza: 50KHz)

Viene prodotto un ritardo di 10.3μS (errore relativo del +3%):

Ritardo di 100μS (periodo: 200μS, frequenza: 5KHz)

Viene prodotto un ritardo preciso.

Ritardo di 65000μS (periodo: 130mS, frequenza: 7.69Hz)

Perchè 65000μS ? Giusto per vedere se davvero si poteva utilizzare un unsigned int come argomento :D

Ritardo di 1mS (periodo: 2mS, frequenza: 500Hz)

Viene prodotto un ritardo di 1.020mS (errore relativo: +2%):

Ritardo di 10mS (periodo: 20mS, frequenza: 50Hz)

Viene prodotto un ritardo preciso, da questo punto in poi non si registrano più errori salendo col valore.

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)