Il PIC ha poca memoria: usiamo al meglio le memorie SD con i microcontrollori della Microchip

001

In questo articolo esamineremo le tecniche che permettono di usare le memorie esterne SD con i microcontrollori PIC. Tanti trucchi e segreti per utilizzare al meglio queste schede e memorizzare una grande quantità di dati su vari dispositivi.

I microcontrollori, per quanto potenti essi siano, sono dotati di una memoria non volatile estremamente limitata. Una semplice MCU è, infatti, non adatta a memorizzare, nel tempo, una notevole quantità di dati come, ad esempio, un brano musicale in formato MP3, le rilevazioni delle condizioni climatiche di un intero anno o i dati della tensione elettrica di una batteria nell'arco di un mese.

Anche la più semplice ed utile applicazione richiede quasi sempre una memorizzazione dei dati in vasta scala e ciò non può essere effettuata usando solamente un PIC.

Per fortuna, i compilatori più evoluti mettono a disposizione dell'utente alcune librerie che permettono di consentono ed utilizzare le memorie di massa di tipo SD e MMC.

Le memorie MMC

Questo tipo di memoria Flash, Multi Media Card, sempre meno utilizzata, è un ottimo supporto di archiviazione per macchine fotografiche digitali, lettori musicali ed altri dispositivi simili. La dimensione massima ammonta a parecchi Gigabyte di spazio disponibile.

Le memorie SD

Le memorie SD (Secure Digital) sono anch'esse dispositivi di tipo Flash basate sulle più vetuste MMC. Anch'esse dispongono di grande capacità di memorizzazione e si usano in tutti i dispositivi portatili e non, come fotocamere, videocamere ed altri.

Tecnicamente si tratta di dispositivi di memorizzazione allo stato solido. La loro dimensione, estremamente ridotta, li rende eccezionalmente adatti a qualsiasi impiego. Inoltre possono essere scritte tantissime volte e trattengono le informazioni anche senza alimentazione elettrica.

Le SD sono, dal punto di vista fisico, leggermente più spesse delle MMC e non sono compatibili con i lettori di queste ultime. Viceversa, le memorie MMC possono essere inserite facilmente in un adattatore per SD.

Perché collegare una SD al PIC?

Sono molteplici i motivi che spingono i progettisti a corredare il proprio progetto di una copiosa quantità di memoria. Soprattutto nelle applicazioni di monitoraggio ed acquisizione dati, il ruolo rivestito da un'ampia memoria di massa è estremamente importante.

A grandi linee ecco alcune applicazioni pratiche che trovano riscontro nell'adozione di una SD in un progetto a microcontrollore:

  • Per conservare e riprodurre foto ed immagini in un sistema corredato di un display grafico;
  • Per conservare ed eventualmente eseguire brani musicali;
  • Per acquisire e memorizzare segnali analogici dall'esterno (es: temperature, tensioni, ecc);
  • Per prevedere frasi, parole e informazioni da proporre all'utente finale;
  • E molto altro......

L'adattatore

Prima di iniziare a parlare della comunicazione tra SD e PIC è opportuno approfondire il discorso sul collegamento tra i due componenti. Sebbene la connessione risulti abbastanza semplice, la particolare piedinatura delle memorie flash ne discrimina leggermente l'uso. Occorre adottare delle soluzioni che non arrechino danno alla memoria. Allo scopo si può scegliere quale adottare tra le seguenti due.

Prima soluzione

Riservata soprattutto a chi dispone della scheda di sviluppo EasyPic, consiste semplicemente nell'acquistare un adattatore ad hoc per le schede SD. Si tratta di un apposito slot che permette lettura e scrittura delle SD tramite protocollo SPI (come vedremo in seguito). Tale dispositivo si può collegare indifferentemente alle MCU che lavorano a 3,3V e a 5V. La connessione avviene attraverso il connettore di tipo IDC10 ma può essere facilmente modificata, secondo le proprie esigenze.

Seconda soluzione

La seconda soluzione è decisamente più interessante ed economica. Non è adatta per usi professionali, commerciali e definitivi ma si presta bene in caso di emergenza e per messa a punto dei dispositivi. Consiste nella costruzione "fai da te" di tale adattatore. Basta utilizzare due serie di connettori, saldati molto vicini tra loro. Una fila deve essere opportunamente piegata per permettere l'inserimento "sicuro" della scheda SD. In commercio tali connettori si chiamano "Header a due vie" o "Header board-board". Se la piega è ben effettuata, il contatto con la memoria sarà sicuro e affidabile. Inoltre essa può essere rimossa all'occorrenza senza traumi poiché risulta semplicemente "incastrata" e non saldata.

Schema elettrico

La connessione di una SD ad un PIC è estremamente semplice. I pin 1, 2, 5 e 7 della SD devono essere collegati ad altrettanti pin del PIC, nell'esempio rispettivamente alle porte RC0, Rc5, RC3 e RC4. La rete resistiva che si vede nello schema costituisce un sistema di partitori che limita la tensione del PIC da 5V a 3,3V, compatibili con il funzionamento della memoria. Essa deve, pertanto, essere alimentata a tale tensione, per evitare di distruggerla.

Lo schema seguente costituisce, invece, una soluzione alternativa, che non fa uso di partitori (come da esempi della MikroElektronika). Esso sarà utilizzato durante le prove delle memorie; il microcontrollore adottato è il Pic 18F4550. Le linee di comunicazione con la memoria esterna sono coadiuvate da altrettante resistenze di pull-up. Tale soluzione è particolarmente consigliata in caso di simulazione circuitale digitale.

Le librerie del mikroBasic

La gestione della memoria MMC o SD, a basso livello, è un'operazione estremamente lunga, pesante e difficoltosa. Il sistema di sviluppo mikroBasic mette a disposizione del programmatore una libreria di funzioni che agevola di molto tale implementazione. Sebbene esse non siano, a volte, di immediata comprensione, offrono una via per utilizzare tali memorie in maniera pressoché indolore.

I prossimi esempi si concentreranno esclusivamente su una singola argomentazione, in modo da focalizzare esattamente una sola operazione di accesso, in modo che l'utente possa studiarla in modo approfondito senza essere "bombardato" da lunghi e tediosi esempi che, molto spesso, i sistemi di sviluppo mettono a disposizione.

Le prove pratiche saranno rivolte alle seguenti operazioni di base:

  • Creazione e scrittura su un file;
  • Accodamento di dati ad un file esistente;
  • Cancellazione di un file;
  • Lettura da un file;
  • Gestione cartelle.

Le ultime versioni di mikroBasic offrono un supporto avanzato e molte nuove funzioni sono state aggiunte. Si consiglia, pertanto, di utilizzare l'ambiente di sviluppo aggiornato.

Creazione e scrittura su un file

Iniziamo con il primo esempio essenziale ma importante: quello della creazione di un file e della scrittura di alcuni caratteri all'interno di esso. La gestione delle memorie esterne è affidata alla comunicazione SPI, infatti occorre utilizzare microcontrollori che abbiano implementata tale possibilità a livello hardware. Il listato, ridotto all'osso, è molto semplice. Le operazioni compiute, nell'ordine, sono le seguenti:

  1. Inizializzazione della comunicazione SPI, con la funzione SPI1_Init();
  2. Inizializzazione della comunicazione con la memoria SD, tramite la funzione Mmc_Fat_Init();
  3. Assegnazione della data e dell'ora al file con la funzione Mmc_Fat_Set_File_Date(2013,11,27,18,10,0);
  4. Impostazione del nome del file da creare, con la funzione Mmc_Fat_Assign("saluti.txt",0xA0);
  5. Predisposizione del file alla scrittura, con la funzione Mmc_Fat_Rewrite();
  6. Scrittura "fisica", con la funzione Mmc_Fat_Write("Un saluto ai lettori di ELETTRONICA OPEN SOURCE.", 48);
  7. Chiusura definitiva del file con la funzione Mmc_Fat_Close(). E' sempre buona norma chiudere i files aperti.

E' importante sottolineare il fatto che il programma sovrascrive il file eventualmente esistente, rimpiazzandolo. Il diodo LED serve semplicemente a controllare l'intero periodo della scrittura su disco, dopo la quale esso si spegne definitivamente.

Inoltre è da tenere conto che la gestione dei files non prevede l'assegnazione di nomi lunghi.

program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_Set_File_Date(2013,11,27,18,10,0)
   Mmc_Fat_Assign("saluti.txt",0xA0)
   Mmc_Fat_Rewrite()
   Mmc_Fat_Write("Un saluto ai lettori di ELETTRONICA OPEN SOURCE.", 48)
   Mmc_Fat_Close()
   portd.0=0    'Spegne Led
end.
Se si ha l'esigenza di "andare a capo" occorre inserire, come di consueto, i caratteri CR+LF a fine di ogni riga. A tale scopo essi saranno contenuti all'interno di una stringa di comodo, da utilizzarsi all'occorrenza. Essa sarà dichiara all'inizio del programma con tutte le modifiche richieste:
dim a_capo as string[2]
a_capo[0]=chr(13)     ' CR
a_capo[1]=chr(10)     ' LF
Mmc_Fat_Write("Un saluto",9)
Mmc_Fat_Write(a_capo,2)    ' CR+LF
Mmc_Fat_Write("ai lettori di",13)
Mmc_Fat_Write(a_capo,2)    ' CR+LF
Mmc_Fat_Write("ELETTRONICA OPEN SOURCE.",24)

Accodamento di dati ad un file esistente

Si tratta dell'esigenza più diffusa in un sistema di acquisizione dati. Ogni qualvolta l'informazione viene acquisita dai sensori (tensione, temperatura, ecc) deve essere memorizzata sulla memoria di massa, in accodamento agli altri dati esistenti, senza comportare la sovrascrittura e la perdita delle precedenti informazioni. In questo caso è sufficiente prevedere l'apertura del file di destinazione in modalità "append" tramite la funzione Mmc_Fat_Append(). Per il resto, la filosofia di funzionamento è la medesima del precedente listato.
program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
dim a_capo as string[2]
dim k as word
txt as string[5]
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   a_capo[0]=chr(13)     ' CR
   a_capo[1]=chr(10)     ' LF
   Mmc_Fat_Set_File_Date(2013,11,27,18,10,0)
   Mmc_Fat_Assign("numeri.txt",0xA0)
   Mmc_Fat_Append()
   for k=1 to 30
       WordToStr(k, txt)
       Mmc_Fat_Write(txt,5)
       Mmc_Fat_Write(a_capo,2)    ' CR+LF
   next k
   Mmc_Fat_Close()
   portd.0=0    'Spegne Led
end.

Cancellazione di un file

Questa operazione è estremamente semplice. E' sufficiente, infatti, inizializzare la comunicazione SPI, la memoria di massa, specificare il file da cancellare senza alcuna modalità d'apertura e, finalmente, invocare la funzione di cancellazione file Mmc_Fat_Delete().
Gli esempi, da soli, forniscono una esatta visione della strategia da seguire.
program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_Assign("saluti.txt", 0)
   Mmc_Fat_Delete()
   portd.0=0    'Spegne Led
end.

Lettura di un file

La lettura file è pienamente supportata dalle librerie del mikroBasic. Essa avviene byte per byte. Se l'informazione è multipla (formata da molti bytes) è possibile risalire ad essa e ricostruirla attraverso opportuni calcoli aritmetici.
L'esempio che segue realizzerà una lettura di cinque temperature dalla SD, precedentemente memorizzate su di essa. Le temperature sono state salvate codificandole in corrispondenti byte (ad esempio 22 gradi corrispondono al carattere ASCII 22 e così via). La struttura del file (temperat.bin), a livello binario, è la seguente:
Il file contiene 5 bytes, corrispondenti ad altrettante temperature, codificate in esadecimale: 0F-11-13-18-1C sono equivalenti ai rispettivi valori decimali 15°, 17°, 19°, 24° e 28°.
La sequenza di lettura, in pseudo-linguaggio, prevede i seguenti passi:
  • Inizializzazione SPI;
  • Inizializzazione MMC;
  • Scelta del nome del file;
  • Impostazione modalità di lettura (Reset);
  • Lettura primo carattere;
  • Lettura secondo carattere;
  • Lettura terzo carattere;
  • Lettura quarto carattere;
  • Lettura quinto carattere.

I caratteri letti possono, ovviamente, essere utilizzati secondo le proprie esigenze (visualizzazione, statistiche, ecc).

program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
dim size as longword
dim character as byte
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_Assign("temperat.bin",0)
   Mmc_Fat_Reset(size)
   Mmc_Fat_Read(character)    ' Legge la prima temperatura
   ......................
   Mmc_Fat_Read(character)    ' Legge la seconda temperatura
   ......................
   Mmc_Fat_Read(character)    ' Legge la terza temperatura
   ......................
   Mmc_Fat_Close()
end.
Il programmatore rivolga la propria attenzione alle seguenti funzioni:
  • Mmc_Fat_Reset(size) è una funzione che predispone il file in modalità lettura. Essa resetta il puntatore spostandolo all'inizio del file assegnato, in modo che esso sia correttamente letto. Il parametro "size", passato per riferimento, contiene la lunghezza del documento, espressa in bytes. "Size" è una variabile di tipo longword;
  • Mmc_Fat_Read(character) è una funzione che legge un carattere dal file e ne sposta il puntatore alla successiva posizione. Il parametro passato è di tipo carattere. Ogni volta che viene invocata, essa legge il prossimo byte del file.

Gestione delle cartelle

La libreria del mikroBasic gestisce in maniera egregia anche le operazioni sulle cartelle. Essa prevede tutte le operazioni basilari sulle directory, come la creazione, la cancellazione, la modifica del nome e lo spostamento all'interno del file system. Le funzioni sono estremamente semplici da utilizzare e la loro implementazione è indolore anche se, dietro le quinte, esiste una notevole mole di codice assembler che l'utente (fortunatamente) non percepisce.

Creazione di una cartella

Per la creazione delle directory si può invocare la funzione Mmc_Fat_MakeDir che accetta, come parametro, il nome della directory, sotto forma di stringa. Anche queste funzioni non sopportano i nomi lunghi. Il seguente listato crea, sulla radice principale, tre cartelle:

  • cartella Sicilia;
  • cartella Lazio;
  • cartella Piemonte.
program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_MakeDir("sicilia", 0x80)
   Mmc_Fat_MakeDir("lazio", 0x80)
   Mmc_Fat_MakeDir("piemonte", 0x80)
   portd.0=0    'Spegne Led
end.

Spostamento in una cartella

Per effettuare operazioni all'interno di una cartella occorre, ovviamente, entrarvi dentro. Questa operazione si effettua tramite la funzione Mmc_Fat_ChangeDir che seleziona la cartella specificata come parametro.
Il listato che segue permette al sistema di accedere all'interno della cartella "Sicilia" e creare nove sottocartelle indipendenti.
program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_ChangeDir("sicilia")
   Mmc_Fat_MakeDir("palermo",  0x80)
   Mmc_Fat_MakeDir("catania",  0x80)
   Mmc_Fat_MakeDir("messina",  0x80)
   Mmc_Fat_MakeDir("enna",     0x80)
   Mmc_Fat_MakeDir("trapani",  0x80)
   Mmc_Fat_MakeDir("ragusa",   0x80)
   Mmc_Fat_MakeDir("siracusa", 0x80)
   Mmc_Fat_MakeDir("caltanis", 0x80)
   Mmc_Fat_MakeDir("agrigento", 0x80)
   portd.0=0    'Spegne Led
end.

Modifica del nome di una cartella

La modifica del nome di una cartella è possibile grazie ad un'altra funzione creata per questo scopo. In essa è sufficiente specificare, come parametri, il vecchio nome e il nuovo nome della cartella. Dopo l'esecuzione del programma, la directory avrà un nuovo nome. Anche in questo caso occorre rispettare la lunghezza massima di otto caratteri.
L'esempio che segue modifica il nome della cartella "Sicilia" in "Trinacr".
program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_RenameDir("sicilia", "trinacr")
   portd.0=0    'Spegne Led
end.

Cancellazione di una cartella

Anche l'ultimo caso, la cancellazione di una cartella dal file-system, è estremamente semplice. Il tutto si basa sulla funzione Mmc_Fat_RemoveDir che effettua la rimozione di una directory, passata come stringa. Il listato che segue cancella definitivamente la cartella "Sicilia" dalla SD.
La cancellazione di una directory è possibile solo se essa è vuota ed esente da altri file o sottodirectory.
program _01
dim Mmc_Chip_Select as sbit at LATB3_bit
dim Mmc_Chip_Select_Direction as sbit at TRISB3_bit
main:
   trisd=0
   portd=0
   ADCON1 = ADCON1 or 0x0F ' Configura AN pins digitali
   CMCON  = CMCON or 7     ' Disattiva i comparatori
   portd.0=1    'Accende Led
   SPI1_Init()
   Mmc_Fat_Init()
   Mmc_Fat_RemoveDir("sicilia")
   portd.0=0    'Spegne Led
end.

Gli attributi dei files

Elenco completo delle funzioni

Ovviamente l'articolo ha trattato le funzioni principali che, poi, sono quelle usate più di frequente. Segue un elenco completo di tutte le funzioni prevista dal mikroBasic, per la gestione della comunicazione con le memorie SD e MMC, presenti nella versione 6.0.0 del sistema di sviluppo adottato (in grassetto quelle esaminate nel presente articolo):

  • Mmc_Init
  • Mmc_Read_Sector
  • Mmc_Write_Sector
  • Mmc_Read_Cid
  • Mmc_Read_Csd
  • Mmc_Multi_Read_Start
  • Mmc_Multi_Read_Sector
  • Mmc_Multi_Read_Stop
  • Mmc_Fat_Init
  • Mmc_Fat_QuickFormat
  • Mmc_Fat_Assign
  • Mmc_Fat_Reset
  • Mmc_Fat_Read
  • Mmc_Fat_Rewrite
  • Mmc_Fat_Append
  • Mmc_Fat_Delete
  • Mmc_Fat_Write
  • Mmc_Fat_Set_File_Date
  • Mmc_Fat_Get_File_Date
  • Mmc_Fat_Get_File_Date_Modified
  • Mmc_Fat_Get_File_Size
  • Mmc_Get_File_Write_Sector
  • Mmc_Fat_Get_Swap_File
  • Mmc_Fat_Tell
  • Mmc_Fat_Seek
  • Mmc_Fat_Rename
  • Mmc_Fat_MakeDir
  • Mmc_Fat_RenameDir
  • Mmc_Fat_RemoveDir
  • Mmc_Fat_ChangeDir
  • Mmc_Fat_Exists
  • Mmc_Fat_Dir
  • Mmc_Fat_ReadDir
  • Mmc_Fat_Activate
  • Mmc_Fat_ReadN
  • Mmc_Fat_Open
  • Mmc_Fat_Close
  • Mmc_Fat_EOF

Conclusioni

Spesso e volentieri, i sistemi di sviluppo sono accompagnati da esempi e listati dimostrativi enormi e lunghi che, inevitabilmente, disorientano il principiante. Lo scopo di questo articolo è quello di far comprendere, con pochi ma chiari e semplici concetti, come avviene la comunicazione tra un microcontrollore ed una memoria SD o MMC.
In tale maniera, l'apprendimento del metodo avviene velocemente e senza alcuna distrazione. Una volta acquisita la conoscenza, il programmatore può approfondire gli argomenti, sicuro di possedere una solida e chiara base iniziale.
Buon lavoro.

 

GDM

 

Quello che hai appena letto è un Articolo Premium reso disponibile affinché potessi valutare la qualità dei nostri contenuti!

 

Gli Articoli Tecnici Premium sono infatti riservati agli abbonati e vengono raccolti mensilmente nella nostra rivista digitale EOS-Book in PDF, ePub e mobi.
volantino eos-book1
Vorresti accedere a tutti gli altri Articoli Premium e fare il download degli EOS-Book? Allora valuta la possibilità di sottoscrivere un abbonamento a partire da € 2,95!
Scopri di più

6 Comments

  1. adrirobot 31 dicembre 2013
  2. delfino_curioso delfino_curioso 31 dicembre 2013
  3. Marven 31 dicembre 2013
  4. adrirobot 31 dicembre 2013
  5. Marven 31 dicembre 2013
  6. maxvarese 1 gennaio 2014

Leave a Reply

Raspberry Pi 3 GRATIS! (Win10 compatibile)

Fai un abbonamento Platinum (EOS-Book + Firmware), ricevi in OMAGGIO la RASPBERRY 3, inviaci il tuo progetto e OTTIENI IL RIMBORSO