I Micro MSP430 nell’uso pratico – Seconda Parte

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.  Nonostante l’MSP430 di Texas Instruments sia un microcontrollore piuttosto datato, ancora oggi è molto utilizzato e tiene testa ai più moderni chip presenti sul mercato. In questo articolo ne verranno illustrate le caratteristiche ed alcuni esempi applicativi.

Per avere una indicazione dell'efficienza dell’assembler di questa famiglia di microprocessori, quello che segue è lo stesso programma appena illustrato, scritto però in linguaggio macchina (Listato 1).

;******************************
;
; Toggle di P1.0 con una
; quadra di 1/100 di duty cycle
; Particolarità: funzionamento
; a bassissima freq. ~ 1.5Khz
;
;******************************
#include "msp430x20x3 . h"
;————————————————
ORG 0F800h
;————————————————
RESET
mov.w #0280h,SP
mov.w #WDTPW+WDTHOLD,&WDTCTL
bis.b #LFXT1S_2,&BCSCTL3
bic.b #OFIFG,&IFG1
bis.w #SCG1+SCG0,SR
bis.b #SELM_3+DIVM_3,&BCSCTL2
mov.b #0FFh,&P1DIR
clr.b &P1OUT
mov.b #0FFh,&P2DIR
clr.b &P2OUT
loop
bis.b #001h,&P1OUT
mov.w #020,R15
DLY1
dec.w R15
jnz DLY1
bic.b #001h,&P1OUT
mov.w #02000,R15
DLY2
dec.w R15
jnz DLY2
jmp loop
;————————————————
; Interrupt Vectors
;————————————————
ORG 0FFFEh
DW RESET
END

Listato 1

Come si può notare, la dimensione dei listati è simile ed anche le istruzioni. L’occupazione di memoria infatti è di 91 byte per la versione in C e di 74 byte per la versione assembler.

SCRITTURA IN FLASH.C

Questo esempio è l’illustrazione di una delle principali caratteristiche della famiglia dei microprocessori MSP430 FXXXX: la possibilità di accedere in scrittura alla propria memoria codice. In questo particolare esempio la scrittura viene effettuata in due segmenti di memoria chiamati “information memory” e quindi deputati alla memorizzazione di parametri e dati variabili da ritenere anche in assenza di alimentazione. La potenzialità è comunque quella di poter accedere a qualunque area e di gestire le protezioni dei segmenti. Ovviamente, non si tratta di memoria RAM, quindi gli algoritmi di accesso sono stati ridotti al minimo pur conservando un livello di sicurezza tale da proteggere il sistema da accessi non intenzionali. Come indicato nel sorgente, l’esecuzione del programma prevede un ciclo continuo di ri-scritture della flash; dato che ciò avviene in tempi molto contenuti, in fase di debug occorre mettere un breakpoint sull’istruzione NOP indicata (quello all’interno del while) al fine di non far riscrivere troppe volte la flash che sopporta un numero non infinito di scritture (“solo” 100.000 cicli). Nel main possiamo osservare l’inizializzazione del clock per il processore e per la macchina di gestione di accesso alla flash. Viene poi chiamata all’infinito la routine di scrittura in flash e la copia del segmento C nel segmento D. La prima delle funzioni chiamate, la Scrittura_Seg_C, implementa la procedura di accesso alla flash che è ampiamente descritta nella documentazione della famiglia del microprocessore, ma che possiamo riassumere nelle seguenti fasi:

  • Set del bit di erase nel registro di controllo accesso alla flash per richiedere una operazione di cancellazione. Questo set è fatto con la contemporanea scrittura di una chiave di accesso di sicurezza detta FWKEY che permette di evitare che il comando sia scritto per sbaglio.
  • Cancellazione del bit di protezione del settore riconfermando la FWKEY.
  • Una scrittura fittizia per attivare la macchina di scrittura.
  • In questo modo il settore indirizzato è stato cancellato e si può direttamente passare alla scrittura dei dati attivando il bit di write (sempre confermato dalla FWKEY) che predispone la macchina di gestione flash all’accesso.
  • La scrittura vera e propria dei dati che nel nostro caso sono i 64 byte del settore posti al valore di “value”.
  • Cancellazione del bit di write per chiudere correttamente la sequenza di scrittura.
  • Conferma del bit di lock della flash comprensiva della FWKEY.

La funzione Copia_Seg_C_in_D implementa lo stesso algoritmo, ma invece di scrivere il valore “value”, nel settore D copia il contenuto del settore C dimostrando come sia possibile accedere a memoria codice e memoria dati nello stesso ciclo “for”, sia in lettura che in scrittura. Il programma è chiaramente dimostrativo e va usato con il breakpoint del quale si è già parlato, in modo da poter verificare l’avanzamento delle varie fasi (Listato 2).

///******************************
// MSP430F20xx Demo
//
// Pin di uscita: nessuno
// Particolarità; Scrittura in
// flash (information memory)
//
//*******************************
#include <msp430x20x3.h>
char data;
// *** Prototipi ***
void Scrittura_Seg_C (char data);
void Copia_Seg_C_in_D (void);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
FCTL2 = FWKEY + FSSEL0 + FN1;
data = 0;
while(1)
{
Scrittura_Seg_C(data++);
Copia_Seg_C_in_D();
_NOP();
}
}
void Scrittura_Seg_C (char data)
{
char *Flash_ptr;
unsigned int i;
Flash_ptr = (char *) 0x1040;
FCTL1 = FWKEY + ERASE;
FCTL3 = FWKEY;
*Flash_ptr = 0;
FCTL1 = FWKEY + WRT;
for (i=0; i<64; i++)
{
*Flash_ptr++ = data;
}
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
}
void Copia_Seg_C_in_D (void)
{
char *Flash_ptrC;
char *Flash_ptrD;
unsigned int i;
Flash_ptrC = (char *) 0x1040;
Flash_ptrD = (char *) 0x1000;
FCTL1 = FWKEY + ERASE;
FCTL3 = FWKEY;
*Flash_ptrD = 0;
FCTL1 = FWKEY + WRT;
for (i=0; i<64; i++)
{
*Flash_ptrD++ = *Flash_ptrC++;
}
FCTL1 = FWKEY;
FCTL3 = FWKEY + LOCK;
}

Listato 2

CONVERTITORE SIGMADELTA.C

In questo programma si comincia a fare un uso contemporaneo di più risorse del microprocessore. Il convertitore analogico/digitale sigma-delta “legge” un canale analogico connesso al sensore di temperatura interno al microprocessore, campionandolo ogni 240ms. Il valore rilevato viene comparato con la precedente lettura e se la differenza è maggiore di 0,5 gradi centigradi (circa) il LED connesso alla porta P1 viene acceso, altrimenti viene spento. Per generare la tempistica del campionamento si utilizza il watchdog e la ISR viene usata per dare lo start al convertitore per la lettura successiva. Questo banale rilevatore di variazioni di temperatura suggerisce interessanti progetti quali il controllo di caricabatterie, termostati e sicurezze varie su circuiti di potenza. Vediamo più nel dettaglio il sorgente ultra-compatto. La define ADC_Delta rappresenta il valore decimale corrispondente a mezzo grado Celsius nella scala di lettura del convertitore, date le impostazioni prescelte. Segue la definizione della variabile usata per la memorizzazione del valore precedente. Vi sono poi sette righe di impostazioni nelle quali viene attivato il watchdog ed abilitato l’interrupt ad esso associato, attivata la porta di output e programmato il modo di funzionamento del convertitore analogico/digitale. Il processore viene quindi mandato in modalità low power LPM0 in attesa di interrupt. Con la direttiva #pragma vector=SD16_VECTOR si informa il compilatore che la funzione che segue è l’handler di gestione dell’interrupt, che ha come vettore SD16_VECTOR. In questo modo il compilatore metterà automaticamente, all’indirizzo del vettore specificato, un salto alla funzione indicata. Il tipo __interrupt per la funzione void SD16ISR(void) specifica che si tratta di un handler di interrupt e quindi l’istruzione finale dell’assembler corrispondente non deve essere una RET (ritorno da call) ma una RETI (ritorno da handler di interrupt. Nel corpo della funzione che sarà attivata dall’interrupt di fine conversione del convertitore, c’è l’analisi della lettura effettuata e la conseguente azione sul LED. A questo punto il convertitore attiverà un altro ciclo di conversione solo quando l’handler dell’interrupt del watchdog provvederà a dare un nuovo segnale di start. Il debug di questo programma è molto semplice e “curioso”: dopo aver dato il run al programma, sarà sufficiente alitare sulla vostra scheda target per vedere accendere il LED (a meno che non stiate eseguendo il debug a 37°C ...) (Listato 3).

///******************************
// MSP430F20xx Demo
//
// Pin di uscita: P1.0
// Particolarità; Misuratore di
// variazione di temperatura
//
//*******************************
#include <msp430x20x3.h>
#define ADC_Delta 31 // ~0.5 ° C
// Var. per Ultimo Valore Letto
static unsigned int U_V_L;
void main(void)
{
BCSCTL2 |= DIVS_3;
WDTCTL = WDT_MDLY_32;
IE1 |= WDTIE;
P1DIR |= 0x01;
SD16CTL = SD16REFON+SD16SSEL_1;
SD16INCTL0 = SD16INCH_6;
SD16CCTL0 = SD16SNGL + SD16IE ;
_BIS_SR(LPM0_bits + GIE);
}
// Handler interrupt dell’ADC
#pragma vector=SD16_VECTOR
__interrupt void ADC_handl(void)
{
if(SD16MEM0 <= UVL + ADC_Delta)
P1OUT &= ~0x01;
else
P1OUT |= 0x01;
Ultimo_Valore_Letto = SD16MEM0;
}
// Handler interrupt del watchdog
#pragma vector=WDT_VECTOR
__interrupt void wtchdg_tim(void)
{
SD16CCTL0 |= SD16SC;
}

Listato 3

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend