Sul blog di Elettronica Open Source puoi leggere non solo tutti gli articoli Premium riservati agli abbonati Platinum 2.0 e inseriti nella rivista Firmware 2.0 (insieme ad articoli tecnici, progetti, approfondimenti sulle tecnologie emergenti, news, tutorial a puntate, e molto altro) ma anche gli articoli della Rubrica Firmware Reload. In questa Rubrica del blog abbiamo raccolto gli articoli tecnici della vecchia rivista cartacea Firmware, che contengono argomenti e temi evergreen per Professionisti, Makers, Hobbisti e Appassionati di elettronica. I dispositivi dsPIC30F dispongono di una periferica di comunicazione UART dotata di funzione Auto Baud, una caratteristica che in diverse occasioni può risultarci molto utile.
Introduzione
Tutti gli attuali dsPIC30F sono dotati di una periferica UART con funzione Auto Baud. Il segnale presente sul pin di ingresso della periferica di comunicazione (RX pin) può essere letto da un modulo Input Capture per rilevare i tempi di ricezione dei fronti di salita e discesa del segnale. A partire da questi si può ottenere il corretto baud rate di funzionamento della periferica. La funzione Auto Baud è utile quando il baud rate del segnale in ingresso non è noto e non è nota la frequenza dell’oscillatore del processore. Per esempio, gli oscillatori RC sono caratterizzati da uno scostamento in frequenza che rende spesso opportuno disporre di una funzione Auto Baud.
METODO
Il metodo su cui si basa l’Auto Baud fa riferimento ai dati contenuti nel segnale ricevuto. E’ solitamente possibile ricorrere ad un protocollo di comunicazione in cui il segnale si presta ad essere analizzato in tal senso. I tempi di ricezione del segnale si possono usare per calcolare i valori che servono per predisporre i registri U1BRG o U2BRG dedicati ai baud rate della periferica UART. I due esempi riportati fanno riferimento al valore corrispondente al carattere ASCII "U" per calcolare il valore che genera il baud rate. Si può usare anche un valore diverso, in generale più sono i fronti nel segnale (cambiamenti di stato dei bit) e più accurato è il risultato.
SEGNALI
I segnali UART vengono inviati con il bit meno significativo all’inizio, preceduti da un bit di start (zero) e seguiti da un bit di stop (uno). Ci sono di solito otto bit che compongono ogni singolo dato, ma si possono usare diverse dimensioni e si può usare un bit di parità in fondo. Questi bit influenzano il calcolo del baud rate, in ogni caso i dati vanno conosciuti in anticipo. Ci sono sempre almeno due fronti contando i bit di start e di stop; nel caso del carattere ASCII relativo alla U come si è considerato ci sono dieci fronti (vedi Figura 1 e Figura 2).
TEMPI E CAMPIONATURA
L’equazione riportata in Figura 3 può essere usata per calcolare il valore da inserire nel registro UxBRG dopo aver registrato i tempi dei fronti del segnale e aver eliminato l’offset di t0. Il calcolo va fatto dopo che l’ultimo fronte è stato registrato e ultimato prima dell’arrivo del bit di start del byte successivo, per evitare la perdita di dati. Va perciò controllato il tempo di esecuzione del calcolo perché non superi un certo limite. E’ bene controllare se sono presenti errori: è possibile che il segnale non contenga il valore atteso di 0x55. Ci può essere un errore apparente dovuto ad un lungo intervallo di tempo fra due fronti consecutivi, e questo può essere rilevato tramite un semplice time-out. Se i tempi relativi a tutti i fronti del segnale rientrano entro un certo periodo è ancora possibile che essi non corrispondano alla sequenza attesa. Ci sono molti metodi statistici che permettono di stabilire con quale grado il segnale registrato devia da quello atteso. Si considera una media di tutte le deviazioni dai valori attesi: se è più del 5% dell’intervallo del singolo bit, il dato viene scartato.
Metodi alternativi
Il metodo di regressione lineare è caratterizzato da una eccellente precisione, dal momento che fa uso di tutte le misure fornite al modulo input capture. Può risultare però troppo lento e dispendioso dal punto di vista computazionale. L’equazione riportata in Figura 4 fa riferimento ad esso e usa i tempi relativi a due fronti del segnale; un’operazione di traslazione equivale ad una divisione per potenze di due. Il codice riportato in appendice C usa questo metodo alternativo.
ESEMPI DI CODICE
Il codice riportato mostra un’implementazione dell’Auto Baud fatta considerando il carattere ASCII 0x55, relativo alla lettera "U". Il codice è stato sviluppato facendo riferimento all’ambiente MPLAB® C30.
Struttura
Il software si divide in tre parti principali: il main loop, l’inizializzazione e le routine di interrupt.
MAIN LOOP
La funzione main () contiene un loop che mostra come funziona il codice dell’Auto Baud. Inizia con la chiamata alla funzione SetupAutoBaud() che serve per inizializzare tutte le periferiche e gli interrupt usati dalla procedura di Auto Baud. Il codice attende fino a quando nel registro U1BRG non viene scritto un valore diverso da zero: ciò significa che la procedura è stata completata con successo. Il codice calcola il valore del baud rate a partire dal valore che si trova nel registro U1BRG e lo invia alla periferica UART. Non è necessario calcolare il baud rate perché funzioni l’Auto Baud, ma è fatto a scopo dimostrativo. Dopo l’invio considerato, il codice inizia un nuovo loop e una nuova procedura di Auto Baud.
int main (void) { while(1) { SetupAutoBaud (); while(U1BRG == 0) {} BaudRate = (Fcy /16) / (U1BRG +1); printf(“Baud rate: %ld\r”, BaudRate); while (U1STAbits.TRMT == 0) {} } } }
INIZIALIZZAZIONE
La funzione SetupAutoBaud() inizializza la periferica UART 1, il modulo Input Capture 1 e il Timer 3 per effettuare l’Auto Baud sui dati presenti nel segnale in ingresso. La periferica UART 1 viene accesa e la funzione Auto Baud attivata; questo fa si che il segnale seriale in ingresso sul pin U1RX venga letto come input dal modulo input Capture 1. Il Timer 3 viene predisposto perché si incrementi ad ogni ciclo di istruzione per ottenere la massima risoluzione; il Timer raggiunge il massimo del conteggio corrispondente ad un registro a 16 bit e ciò fissa il periodo corrispondente. Il modulo Input Capture 1 viene predisposto a leggere il Timer 3 e genera un interrupt in corrispondenza di ogni fronte del segnale in arrivo; viene attivato l’interrupt relativo al modulo Input Capture 1.
ROUTINE DI INTERRUPT
Ci sono due routine di interrupt, una per il Timer 3 e una per il modulo Input Capture 1. La routine di interrupt del Timer 3 conta gli interrupt provocati dal reset del timer. Se c’è più di un reset tra i fronti significa che l’Auto Baud non ha funzionato e la procedura inizia nuovamente. Questo succede se si supera un certo intervallo di tempo tra fronti del segnale in arrivo. La routine di interrupt del modulo Input Capture è al cuore della procedura di Auto Baud; differisce a seconda che si ricorra ad un semplice calcolo o ad una più complessa operazione di regressione. La routine di interrupt inizia salvando il tempo relativo all’ultimo fronte e leggendo il nuovo tempo del fronte appena rilevato; il timer viene resettato per conteggiare un nuovo intervallo (time-out). Un interrupt del modulo Input Capture abilita l’interrupt del Timer 3 che rileva un nuovo reset e inizializza le variabili del calcolo della procedura di Auto Baud. Ogni interrupt successivo del modulo Input Capture viene utilizzato per avere un valore di tempo da sottrarre al precedente per ottenere l’intervallo relativo al bit corrente; questo viene fatto in aritmetica senza segno. Nel caso di un semplice calcolo l’intervallo di tempo di ogni singolo bit è addizionato a dare una somma parziale fino a quando otto intervalli sono stati sommati assieme. Nel caso di un calcolo che fa ricorso ad una regressione, l’intervallo di tempo relativo ad ogni bit e sommato a quello rilevato precedentemente e salvato come successivo elemento in una sequenza di tempi. Questo fornisce i punti per il calcolo della regressione e la verifica successiva dell’errore; le due somme che intervengono nel calcolo della regressione sono svolte nella routine di interrupt. Quando viene rilevato l’ultimo interrupt del modulo Input Capture, (il decimo), la routine disabilita entrambi gli interrupt, termina il calcolo della procedura di Auto Baud e abilita la periferica UART con il nuovo baud rate. Nel caso del semplice calcolo non c’è una verifica d’errore, a parte il rilevare i time out se il valore da scrivere nel registro U1BRG è determinato direttamente dalla somma degli intervalli di tempo degli otto bit. Il numero è arrotondato sommando ad essa 64 e dividendo per 128 mediante una traslazione di sette bit: questo aggiunge ½ prima di troncare. Nel caso del calcolo della regressione si considera la pendenza e l’intercetta con l’asse delle Y di una retta. Questi valori servono per calcolare i valori attesi da sottrarre a quelli rilevati per stabilire un errore; se questo supera una percentuale del 5% la procedura di Auto Baud viene rifatta; tale soglia si può modificare a seconda dell’accuratezza che si desidera. Il valore da scrivere nel registro U1BRG si ricava dalla pendenza della retta. Il codice seguente riporta la routine di interrupt del modulo Input Capture1.
Void_ISR_IC1Interrupt(void) {IFS0bits.IC1F = 0; PreviousCapture = CurrentCapture; CurrentCapture = IC1BUF; T3Count = 0; If (ICCount == 0 ) { IFS0bits.T3IF = 0; IEC0bits.T3IE = 1; RegressionData[0] = 0; SumY = 0; SumXY = 0; } Else {CaptureDifference = CurrentCapture – Previous Capture; RegressionData [ICCount] = RegressionData[ ICCount-1] + CaptureDifference; SumY += RegressionData[ICCount]; SumXY += RegressionData[ICCount] * ICCount; } ICCount++; If (ICCount == 10) { IEC0bits.IC1IE = 0; IEC0bits.T3IE = 0; CalculateBaud (); } }
La routine del Timer 3 è riportata di seguito.
void_ISR_T3Interrupt(void) {IFS0bits.T3IF = 0; T3Count++; if(T3Count == 2) { SetupAutoBaud(); } }
UTILIZZO DEL CODICE
Il codice si può testare su una scheda dsPICDEM™ 1.1 e utilizzando un dsPIC30F6014 ad una velocità di 29,5 MIPS. Essa permette di considerare valori di baud rate fino a 600 baud. Si possono seguire i seguenti passi per testare il codice:
- Collegare tramite un cavo RS232 una porta COM del PC al connettore chiamato “PORT B” sulla dsPICDEM 1.1
- Eseguire un programma tipo Hyper Terminal sul PC e assicurarsi che usi la porta COM corretta
- Compilare il codice, programmare il dsPIC® e far eseguire il codice
- Digitare “U” dal programma del PC
- La scheda risponderà con il messaggio “Baud rate: xxxx” indicando il baud rate che si sta usando
- Cambiato il baud rate, si può digitare nuovamente “U” dal programma del PC
- La scheda risponderà con un nuovo baud rate
RISORSE UTILIZZATE
La procedura di Auto Baud fa ricorso alla memoria di programma e dei dati, un modulo input Capture, un timer e la periferica UART. Si impiega poca RAM, e timer e modulo input capture si possono riutilizzare dopo che la procedura di Auto Baud è completata. L’utilizzo della memoria di programma dipende dal livello di sofisticazione del calcolo. La Figura 5 mostra un esempio di utilizzo della memoria nel caso dei due tipi di calcolo considerati. Le applicazioni dell’ambiente MPLAB C30 fanno uso di un minimo di codice richiesto per lo start-up, l’inizializzazione, e questo non è stato considerato nella figura.
MODIFICHE E MIGLIORAMENTI
Gli esempi di codice considerati mostrano due modi di funzionamento della procedura di Auto Baud su un byte di dati 0x55 corrispondenti al carattere ASCII relativo alla lettera "U"; questi metodi si possono adattare a qualsiasi dato conosciuto in ingresso. Tutti e due i metodi determinano l’intervallo di ogni singolo bit rilevando i tempi dei fronti del segnale d’ingresso. Vari tipi di analisi e rilevazione di errori si possono adottare per migliorare l’attendibilità o la velocità. E’ possibile usare la procedura di Auto Baud su dati non noti ma può essere difficile determinare l’intervallo di tempo di ogni bit e distinguere i bit di start e di stop dai bit di dati. La procedura di Auto Baud dovrebbe nel migliore dei casi usare dati conosciuti per semplificare i calcoli. La procedura di Auto Baud viene fatta ricorrendo ad interrupt. La struttura che predispone la priorità degli interrupt del dsPIC si mostra flessibile e permette di configurare gli interrupt della procedura di Auto Baud, per influenzare il meno possibile il resto dell’applicazione; il Timer e il modulo Input Capture utilizzato dalla procedura possono essere utilizzati dal resto dell’applicazione alla fine del calcolo della procedura di Auto Baud. Entrambe le periferiche UART dispongono della funzione di Auto Baud. L’UART1 può usare il modulo Input Capture 1 e l’UART2 usare il modulo Input Capture 2, così entrambi possono attivare la funzione allo stesso tempo.
CONCLUSIONE
La funzione di Auto Baud rende semplice configurare la periferica UART quando non si conosce il baud rate. La procedura funziona ricorrendo ad interrupt in modo da avere poca influenza sul resto dell’applicazione. Si può adattare il codice nel caso si desideri maggior velocità ricorrendo ad un calcolo semplice; maggior affidabilità e più controllo dell’errore richiedono un calcolo più complesso.