Un algoritmo di controllo e regolazione dell’oscillatore interno DCO del microcontrollore Texas Instruments MSP430: le sue prestazioni lo rendono particolarmente adatto ad applicazioni quali strumentazione di misura, sensoristica intelligente ed elettronica di consumo. Le periferiche sono state progettate per richiedere il minor supporto software possibile. L’algoritmo è stato scritto interamente in linguaggio C ed è suddiviso in due funzioni: il ciclo di taratura del DCO e il controllo della stabilità dell’oscillatore nel tempo.
Introduzione
Il microcontrollore MSP430 di Texas Instruments, è un RISC a 16 bit con architettura von Neumann (figura 1).
Di seguito le principali caratteristiche del micro:
- 1KB-120KB di Flash ISP;
- Fino a 10KB RAM;
- ADC a 10/12/16 bit;
- DAC a 12 bit;
- Comparatore interno;
- Supporto per pilotaggio LCD;
- SVS (Supply Voltage Supervisor);
- Timers a 8 e 16 bit;
- Watchdog timer;
- UART/LIN;
- I2C;
- SPI;
- IrDA;
- Moltiplicatore hardware;
- Controller DMA;
- Sensore di temperatura;
Il convertitore A/D ha un sistema di scansione automatica dei vari ingressi e l’avvio della conversione (che avviene via hardware) avvia un trasferimento dati in DMA. Il sistema di clock di questo microcontrollore è studiato appositamente per applicazioni low-power. Un clock ausiliario a bassa frequenza (ACLK) viene direttamente pilotato da un cristallo a 32KHz o da un oscillatore interno e può essere usato come real-time clock in background. Il sistema DCO (Digitally Controlled Oscillator) fornisce invece i segnali di MCLK (master clock) e SMCLK (Sub-Master Clock) che vengono utilizzati rispettivamente dalla CPU e dalle periferiche. La struttura del sistema di clock è riportata in figura 2.
IL DCO
Questo articolo mostrerà un efficiente algoritmo per il controllo della precisione del DCO interno al microcontrollore dal punto di vista della stabilità dell’oscillazione nel tempo e del ciclo di taratura. Questa periferica del microcontrollore MSP430 è un oscillatore con le caratteristiche di un circuito RC. Come un oscillatore RC la sua frequenza varia in funzione della temperatura e della tensione e, a parità di condizioni, è diversa da componente a componente. Per poter utilizzare questo oscillatore come clock di sistema è necessario quindi tarare la sua frequenza e controllare costantemente il suo valore per correggere le inevitabili variazioni indotte dalle variazioni di temperatura e tensione di alimentazione. Il valore di resistenza che alimenta il DCO che definisce la sua frequenza di oscillazione. È possibile selezionare 8 resistenze interne alla periferica oppure utilizzare una resistenza esterna. Questa ultima scelta permette di stabilizzare le variazioni in temperatura e di raggiungere frequenze più elevate ma non sarà considerata in questo articolo. Il DCO è un oscillatore ad anello a otto stadi quindi, scelta la resistenza che determina la frequenza base di oscillazione, è possibile ottenere fino a otto frequenze diverse. Le due frequenze adiacenti nell’intervallo di otto frequenze selezionato possono essere modulate per ottenere una frequenza intermedia. La modulazione avviene con la formula seguente:
dove fDCO e f(DCO+1) sono le due frequenza adiacenti nell’intervallo selezionato.
MOD indica quante volte viene utilizzata fDCO dal modulatore nel periodo di 32 cicli di clock del DCO.In conclusione si possono selezionare otto diversi intervalli di frequenza per l’oscillatore, che sono parzialmente sovrapposti. All’interno di ogni intervallo sono definite 8 frequenze base che possono essere modulate per ottenere diverse frequenze intermedie I registri interni che controllano il DCO sono:
Il registro BCSCTL1: in questo registro è possibile selezionare la resistenza interna Rsel che alimenta il DCO e quindi definire il gruppo di otto frequenze base. Il registro DCOCTL che controlla il modulatore e consente di ottenere tutte le frequenze intermedie.
La procedura di configurazione dell’oscillatore DCO è la seguente:
- Selezionare il range di frequenze scegliendo la resistenza Rsel (registro BCSCTL1 bit0..2);
- Segliere una frequenza base scelta tra le otto possibili dell’intervallo selezionato (registro DCOCTL bit 5..7);
- Definire la modulazione tra le due frequenze adiacenti fDCO, fDCO+1(registro DCOCTL bit 0..4).
ALGORITMO DI CONTROLLO
Per controllare la frequenza di oscillazione del DCO l’algoritmo utilizza un timer interno al microcontrollore. È possibile scegliere uno qualsiasi dei due timer A o B presenti nell’ MSP430 (nel codice descritto nel listato 1 la definizione DCOuseTMRA o DCOuseTMRB permette di effettuare facilmente questa scelta). L’uscita del DCO, tramite il clock SMCLK, viene utilizzata come clock per il timer selezionato. Uno dei registri del timer è quindi configurato come funzione di capture controllato da un segnale esterno di trigger. Questo segnale cattura periodicamente, nel registro prescelto il valore del timer (figura 3).
La differenza tra due letture successive fornisce il rapporto tra la frequenza di clock del timer e la frequenza del segnale di capture applicato esternamente. Nota la frequenza del segnale di capture è possibile ricavare il valore attuale della frequenza del DCO con la formula:
Il segnale periodico per la funzione di capture viene fornito dal clock interno ACLK, che si ottiene collegando un quarzo, in questo caso da 32KHz, all’oscillatore in bassa frequenza LFXT1CLK. Per avere una migliore approssimazione della frequenza misurata la frequenza del clock ACLK viene ridotta internamente al microcontrollore prima di applicarla al segnale di capture del registro del timer. L’architettura dell’MSP430 prevede la possibilità di collegare il segnale di ACLK direttamente al segnale di capture di un registro del timer. Per conoscere questa configurazione si deve esaminare il datasheet del componente prescelto. In questa applicazione il segnale ACLK è stato diviso per 8 per ottenere la massima risoluzione possibile per il contatore per il calcolo della frequenza del DCO. La formula per ottenere la frequenza di oscillazione del DCO risulta pertanto:
Dove TimerN+1 e TimerN rappresentano due letture successive del registro di capture del timer.
Nota la frequenza del DCO si deve elaborare una procedura di taratura che consenta di raggiungere rapidamente il valore di frequenza desiderato fSET. L’algoritmo descritto in [1] utilizza una funzione denominata p-control che consiste nel modificare la frequenza dell’oscillatore con un valore proporzionale all’errore rilevato (fSET - fDCO). Questa procedura richiede l’esecuzione di una moltiplicazione (fattore di proporzionalità per errore misurato). Molte versioni dell’MSP430 integrano un moltiplicatore hardware che permette di eseguire rapidamente l’operazione. L’algoritmo proposto invece non utilizza moltiplicazioni ma semplicemente confronti ed è quindi utilizzabile anche per le versioni sprovviste del moltiplicatore hardware. Questa procedura, inoltre, esegue la scansione completa delle frequenze generate dall’oscillatore scegliendo poi quella che più si avvicina alla frequenza desiderata. La funzione di taratura si applica solo all’accensione per tarare il DCO. Come descritto in precedenza, le variazioni di temperatura e tensione di alimentazione variano la frequenza del DCO rispetto al punto di taratura raggiunto inizialmente. Queste variazioni avvengono lentamente e possono essere compensate modificando la configurazione del modulatore per far rientrare l’errore fra la frequenza desiderata e quella misurata non rientra nel limite previsto. Perciò durante il normale funzionamento dell’applicazione, si devono effettuare misure periodiche della frequenza del DCO ed eventualmente modificare il registro DCOCTL per variare la configurazione del modulatore. Questo algoritmo di controllo è molto semplice e considera solamente il segno dell’errore fra frequenza attuale e frequenza desiderata del DCO.
DESCRIZIONE DELLE FUNZIONI
Funzione di taratura
La procedura di taratura seleziona la frequenza di oscillazione del DCO che minimizza l’errore assoluto |fSET - fDCO| tra la frequenza desiderata e la frequenza del DCO. Questa procedura, descritta nel diagramma di flusso in figura 4, viene eseguita all’accensione ed esegue la scansione di tutte le possibili frequenze generate dal DCO.
Un ciclo for esterno esegue la scansione di tutte le resistenze interne Rsel collegabili al DCO. Ogni ciclo definisce il range di oscillazione e le otto frequenze base del DCO. All’interno del ciclo, cioè per ogni valore di Rsel, si esegue una procedura suddivisa in tre passi modificando la configurazione del modulatore:
Il DCO viene configurato per oscillare alla frequenza limite inferiore dell’intervallo (DCOCTL=0). Questa frequenza viene confrontata con la frequenza desiderata e se la frequenza del DCO risulta superiore alla frequenza desiderata, quest’ultima non è compresa nell’intervallo selezionato ma risulta inferiore a tutte le frequenze dell’intervallo selezionato. Si deve quindi necessariamente modificare Rsel per selezionare un nuovo intervallo in cui effettuare la ricerca. Se la frequenza limite inferiore dell’intervallo selezionato risulta inferiore a quella cercata è necessario eseguire un nuovo confronto con la frequenza limite superiore dell’intervallo (DCOCTL =0xE0) la frequenza limite superiore dell’intervallo non ammette modulazione.
In questo secondo confronto se la frequenza di oscillazione del DCO è inferiore alla frequenza desiderata allora la frequenza desiderata è superiore a tutte le frequenze dell’intervallo e quindi si deve necessariamente modificare Rsel per selezionare un nuovo intervallo di ricerca. Se invece la frequenza desiderata è inferiore alla frequenza limite superiore allora la frequenza cercata è compresa nell’intervallo selezionato e si deve eseguire la ricerca all’interno dell’intervallo selezionato. Il terzo passo consiste nel cercare all’interno dell’intervallo prescelto la frequenza che meglio approssima la frequenza desiderata. La scansione si effettua con un algoritmo di ricerca binaria modificando il valore del registro DCOCTL partendo dai limiti 0x00..0xE0. Si confronta la frequenza centrale dell’intervallo con fSET e si sposta il limite inferiore/superiore dell’intervallo se la frequenza centrale risulta superiore/inferiore a fSET. L’algoritmo convergerà verso la frequenza che meglio approssima quella cercata. La ricerca binaria permette di limitare i confronti a log2 224 = 7,2 (224 sono i possibili valori per il registro DCOCTL).
Al termine di questa ricerca si confronta l’errore |fSET - fDCO| con il valore calcolato nella precedente approssimazione. Se l’errore risulta inferiore al valore precedente si memorizzano i valori di Rsel e del registro DCOCTL. Dopo aver ripetuto la ricerca per tutti gli 8 intervalli di frequenza la coppia Rsel DCOCTL memorizzata è quella che meglio approssima la frequenza cercata fSET. Si osservi che per ogni intervallo di frequenza, o meglio per ogni possibile resistenza Rsel che alimenta il DCO, si ottiene la migliore approssimazione possibile della frequenza cercata anche se quest’ultima è esterna all’intervallo selezionato. In questo caso l’algoritmo convergerà necessariamente verso il valore massimo o minimo dell’intervallo fornendo un’approssimazione probabilmente grossolana della frequenza desiderata.
PROCEDURA DI CONTROLLO
Questa procedura agisce principalmente sul modulatore del DCO per compensare le variazioni di frequenza dovute a variazioni di temperatura/tensione. La funzione di controllo dev’essere inserita nel ciclo di normale funzionamento dell’applicazione. La funzione utilizza l’interrupt associato al segnale di capture del timer. Ad ogni interrupt viene valutata la differenza tra due successive letture del registro di capture. Periodicamente la funzione di controllo legge questa differenza e valuta l’errore rispetto alla frequenza desiderata. Se l’errore è troppo elevato si interviene sul modulatore per compensare la variazione di frequenza. Il segno dell’errore determina la direzione dello spostamento, la correzione si esegue finchè l’errore non rientra nei limiti previsti.
Realizzazione delle funzioni descritte
Nella descrizione precedente, per semplicità, sono stati omessi alcuni dettagli che invece sono necessari nella realizzazione delle funzioni.
Cambiando la configurazione del DCO si modifica la frequenza di conteggio del timer di controllo. Poiché la modifica della configurazione del DCO avviene in modo asincrono rispetto al segnale di capture, si deve attendere almeno tre interrupt del segnale di capture prima di valutare la nuova frequenza. Nell’implementazione la variabile che determina questo ritardo è delayCCRx. Nella procedura di taratura, i limiti ammessi per il registro DCOCTL sono inferiori ai limiti massimi pre- visti (0x00 e 0xE0). Questa scelta semplifica la succes- siva procedura di controllo periodico che modifica il registro DCOCTL. La procedura di controllo, infatti, potrebbe far raggiungere al registro DCOCTL il valore massimo o minimo, ammessi. In questo caso si dovrebbe selezionare un nuovo valore per Rsel ed eseguire una nuova ricerca binaria sul nuovo intervallo di frequenze per cercare la migliore approssimazione per fSET. Durante la procedura di taratura la variazione del registro DCOCTL potrà avvenire solo tra (0x00+DCOSAFE) e (0xE0- DCOSAFE). L’algoritmo di controllo invece potrà raggiungere i limiti estremi per il registro DCOCTL ed eventualmente procedere con una nuova ricerca binaria solo se questi limiti vengono superati.
TEMPI DI ESECUZIONE DELL’ALGORITMO
La procedura di taratura per ogni intervallo di frequenze richiede i seguenti confronti:
- Confronto con il limite minimo dell’intervallo selezionato;
- Confronto con il limite massimo dell’intervallo selezionato;
- Al massimo otto confronti per cercare la frequenza all’interno dell’intervallo selezionato.
In totale dieci confronti per otto intervalli di frequenza possibili cioè al massimo 80 confronti. Poiché è necessario attendere almeno tre interrupt di capture dopo ogni modifica del DCO per valutare la nuova frequenza sono necessari 80 * 3 = 240 interrupt di capture per effettuare la scansione completa delle frequenze del DCO. Se si utilizza un segnale ACLK a 32KHz quindi con un segnale di capture di 4KHz cioè un interrupt ogni 250ms il tempo massimo necessario per la taratura del DCO è di 60ms. In realtà il tempo è notevolmente inferiore poiché se la frequenza è esterna all’intervallo selezionato si effettuano solo i controlli limite inferiore e superiore. Inoltre, per ottimizzare l’algoritmo, si può limitare la scansione degli intervalli di frequenza a quelli che includono sicuramente la frequenza cercata.
CONCLUSIONI
L’algoritmo è stato applicato con successo a due microcontrollori MSP430F149 e MSP430F1611. Le applicazioni realizzate non prevedono particolari stati di funzionamento in idle o power down mode. Il controllo della frequenza pertanto viene effettuato continuamente.
Bibliografia:
[1] A. Muehlhofer, “Controlling the DCO frequency of the MSP430x11x”, Texas Instruments applica- tion report slaa074.
[2] “MSP430x1xx family user guide”, Texas
Instruments user guide slau049e.
[3] “MSP430x161x datasheet”, Texas Instruments datasheet slas368d.
Listato codice:
// DCO adjust #include "lxhw.h" #define DCO_SET 2000 // DCO target frequency in KHz #define RSELSET 4 // DOC internal R nominal frequency set 0.13 0.28 0.47 0.75 1.3 2.0 3.2 MHz #define F_REF 32768/8 // ACLK/8 #define TCLK_DIV 1 // Timer A DCO frequency divisor #define FSET 488 // (DCO_SET * 1000)/(F_REF * TCLK_DIV) // (DCO_SET*1000)/TCLK_DIV --> TMRA clock #define DFSET 10 // 2% FSET #define DELAYCCRxSET 3 // 4KHz / 5 = 800Hz --> 1.2ms #define DCOMAX 0xE0 // DCO set frequency max = 7 #define DCOMIN 0x00 // DCO set frequency min = 0 #define DCOSAFE 0x0A // DCO set limit safe area #define MAXRsel 0x07 // Rsel max #define MINRsel 0x00 // Rsel min // timer selection #define DCOuseTMRA 0 #define DCOuseTMRB 1 #if DCOuseTMRA #define TxCTL TACTL #define TxCCTL TACCTL2 #define CCRx TACCR2 #define CFGTxCTL 0x0204 #define CFGTxCCTL 0x5100 #endif #if DCOuseTMRB #define TxCTL TBCTL #define TxCCTL TBCCTL6 #define CCRx TBCCR6 #define CFGTxCTL 0x0204 #define CFGTxCCTL 0x5100 #endif unsigned lastCCRx ; // Last captured value unsigned DCCRx ; // Difference between last two read unsigned char delayCCRx ; // Delay wait read timer unsigned char DCOhi = DCOMAX-DCOSAFE ; // only for calibrate DCO start value unsigned char DCOlo = DCOMIN+DCOSAFE ; unsigned char DCOflags ; #define FDCOTask 0x01 // 1 DCO task request unsigned char DCOmode ; #define MDCOidle 0x00 // Monitor DCO frequency monitor #define MDCOlo 0x01 // Test DCO Rsel min #define MDCOhi 0x02 // Test DCO Rsel max #define MDCOset 0x03 // Find DCO freqeuncy in Rsel range #define MDCOadj 0x04 // Adjust DCO frequency near set value #define MDCOstart 0x05 // Init DCO calibration procedure // interrupt routine #if DCOuseTMRA #pragma vector=TIMERA1_VECTOR __interrupt void DCOfrequencyisr() { if (TxCCTL & CCIFG) { TxCCTL &= ~CCIFG ; // Update DCCRx = SMCLK count between two ACLK/8 rising edges // Memo last captured value DCCRx = CCRx - lastCCRx ; lastCCRx = CCRx ; // Wait until delay CCRx expire // Count more than one time the SMCLK if (--delayCCRx == 0) { delayCCRx = DELAYCCRxSET ; DCOflags |= FDCOTask ; } } } #endif #if DCOuseTMRB #pragma vector=TIMERB1_VECTOR __interrupt void DCOfrequencyisr() { switch(TBIV) { case 0x0C: // TxCCTL &= ~CCIFG ; // Update DCCRx = SMCLK count between two ACLK/8 rising edges // Memo last captured value DCCRx = CCRx - lastCCRx ; lastCCRx = CCRx ; // Wait until delay CCRx expire // Count more than one time the SMCLK if (--delayCCRx == 0) { delayCCRx = DELAYCCRxSET ; DCOflags |= FDCOTask ; } break ; default: break ; } } #endif void WriteRsel(unsigned char Rsel) { unsigned tmpBCSCTL1 = BCSCTL1 ; tmpBCSCTL1 &= 0xF8 ; // Reset RSel bit tmpBCSCTL1 |= Rsel ; BCSCTL1 = tmpBCSCTL1 ; } void DCOfrequencyTask() { unsigned char Rsel ; unsigned Error ; switch (DCOmode) { case MDCOstart: // Configure timers // ACLK/8 internaly connect CCI2B (Caputre timer signal) // TMRx free runnning count UP TxCCTL = CFGTxCCTL ; TxCTL = CFGTxCTL | 0x20 ; // start count // Configure DCO // Start with oscillator R = 4 // DCO to min value (Lower frequency for this Rsel range) DCOCTL = DCOMIN+DCOSAFE ; delayCCRx = DELAYCCRxSET ; // Init DCO claibrate state machine DCOmode = MDCOlo ; break ; // Check the lower frequency range for select Rsel (DCO = min value) case MDCOlo: // IF SMCLK target >= SMCLK count can be the right range // check the upper limit if (FSET >= DCCRx) { DCOCTL = DCOMAX-DCOSAFE ; delayCCRx = DELAYCCRxSET ; DCOmode = MDCOhi ; } // IF SMCLK target < SMCLK count target frequency is out of range (lower side) // Must decrease Rsel else { DCOmode = MDCOidle ; } break ; // Check the upper frequency range for select Rsel (DCO = max value) case MDCOhi: // IF SMCLK target >= SMCLK count frequency is out of range (upper side) // Must increase Rsel if (FSET >= DCCRx) { DCOmode = MDCOidle ; } // IF SMCLK target < SMCLK count target frequency is in range // Select the middle point of freqeuncy rnage and check it else { DCOCTL = (DCOhi+DCOlo) >> 1 ; delayCCRx = DELAYCCRxSET ; DCOmode = MDCOset ; } break ; // Find near freqeuncy in the select range (Rsel fixed) case MDCOset: // IF SMCLK target == SMCLK Found exactly !! if (FSET == DCCRx) { DCOmode = MDCOidle ; } // Look at the upper half range else if (FSET > DCCRx) { DCOlo = DCOCTL+1 ; } // Look at the lower half range else { DCOhi = DCOCTL-1 ; } // if range >= 1 repeat search // Set DCO with the middle frequency point if (DCOhi > DCOlo) { DCOCTL = (DCOhi+DCOlo) >> 1 ; delayCCRx = DELAYCCRxSET ; } // if range = 0 assign nearest frequency else { DCOmode = MDCOidle ; } break ; // DCO frequency monitor case MDCOidle: // frequency set error Error = (FSET > DCCRx) ? (FSET - DCCRx) : (DCCRx - FSET) ; //if error over max set error adjust frequency if (Error > DFSET) DCOmode = MDCOadj ; break ; // If freqeuncy error > max error adjust frequency case MDCOadj: DCOmode = MDCOidle ; // FSET > DCCRx --> SMCLK < SMCLKset (frequency is low) if (FSET > DCCRx) { // change frequency without change Rsel if (DCOCTL < DCOMAX) DCOCTL++ ; else // check upper Rsel limit // ok can select another range // over end and restore idle mode Rsel = BCSCTL1 & 0x07 ; if (Rsel < MAXRsel) { WriteRsel(++Rsel) ; DCOmode = MDCOlo ; } } // FSET < DCCRx --> SMCLK > SMCLKset (frequency is high) if (FSET < DCCRx) { if (DCOCTL > DCOMIN) DCOCTL-- ; else // check lower Rsel limit // ok --> can select another range // under --> end and restore idle mode Rsel = BCSCTL1 & 0x07 ; if (Rsel > MINRsel) { WriteRsel(--Rsel) ; DCOmode = MDCOlo ; } } break ; default: DCOmode = MDCOidle ; break ; } DCOflags &= ~FDCOTask ; } void DCOfrequencyset() { unsigned bestError = 0xFFFF ; unsigned Error ; unsigned char bestDCO ; unsigned char bestRsel ; unsigned char Rsel ; for (Rsel=MINRsel ; Rsel<=MAXRsel ; Rsel++) { WriteRsel (Rsel) ; DCOmode = MDCOstart ; DCOflags |= FDCOTask ; do { // Check capture interupt every 4.096KHz (ACLK/8) if (TxCCTL & CCIFG) { TxCCTL &= ~CCIFG ; // reset interrupt flag DCCRx = CCRx - lastCCRx ; // SMCLK periods in ACLK/8 period lastCCRx = CCRx ; // remember last capture value // Wait until delay CCRx expire // Count more than one time the SMCLK if (--delayCCRx == 0) DCOflags |= FDCOTask ; } if (DCOflags & FDCOTask) DCOfrequencyTask() ; } while (DCOmode != MDCOidle) ; // repeat until frequency found of out of range // calcualte frequency error Error = (FSET > DCCRx) ? (FSET - DCCRx) : (DCCRx - FSET) ; // abs value // remember best frequency cfg if (Error < bestError) { bestRsel = Rsel ; bestDCO = DCOCTL ; bestError = Error ; } } // loop for all Rsel // configure DCO with best frequency WriteRsel (bestRsel) ; DCOCTL = bestDCO ; } void DCOfrequencyadj() { if (DCOflags & FDCOTask) DCOfrequencyTask() ; } // eof
Salve
Si potrebbe inserire un pulsante per scaricare gli articoli in formato pdf?
Grazie
Carlo
In fondo all’articolo, vicino alle tags, hai il pulsante PRINT. Puoi quindi avere una versione printer friendly e quindi stampare, su carta o in PDF.
Gli articoli PREMIUM poi vengono anche inseriti nelle riviste 😉
Ok grazie!
La piattaforma dei MCU MSP430 della TI è stata costruita per applicazioni low power. Ci sono un bel po’ di serie che nel corso del tempo hanno visto migliorare molte specifiche, oltre al clock, soprattutto i consumi e le memorie a disposizione.