MAX7219: Pilotare display a 7 segmenti o matrici di LED è un gioco da ragazzi
Il MAX7219 è un circuito integrato progettato per pilotare fino ad 8 display a 7-segmenti a catodo comune oppure 64 led (una matrice di led 8×8 o una bargraph). Questi accetta in ingresso un segnale seriale e sono necessari solo 3 pin per pilotarlo: dato, clock e latch: il sistema di trasmissione dati è un semplice SPI ed è praticamente uguale a quello che abbiamo visto quando abbiamo pilotato i display a 7 segmenti con un 74HC595, con la differenza che qui il dato da trasmettere è a 16bit e vanno pilotati i registri interni dell’integrato per poter far apparire numeri o lettere sui singoli digits che compongono il display.
Più MAX7219 possono essere collegati in cascata per pilotare display di dimensioni maggiori (è presente un pin DOUT che si collega al pin DIN del driver successivo). Il MAX7219 lavora in multiplexing, normalmente ogni cifra viene scansionata con una frequenza di 100Hz, ma non dobbiamo preoccuparci di questo: gestisce tutto lui! Noi abbiamo solo il compito di impostare i singoli digits ai valori che vogliamo.
Guardate qui cosa ha creato una persona utilizzando 144 display a 7 segmenti, 18 MAX7219 e un Arduino Nano
Il MAX7219 si trova anche in formato DIP, ma quello che a noi interessa è il fatto che sui vari siti di vendite online si trovano a pochi spiccioli dei moduli già pronti con a bordo 8 display a 7 segmenti già collegati ad un MAX7219: consiglio di acquistarlo su Futura Elettronica.
Indice dei contenuti
Trasmissione dato
Come anticipato il dato da inviare è a 16 bit e va inviato dal MSB (bit 15) all’ LSB (bit 0) sul pin DIN. Quindi una volta composto il valore a 16 bit da inviare (oppure possiamo inviare due valori da 8 bit in sequenza), faremo una scansione inversa come abbiamo già visto per il 74HC595. Il dato viene memorizzato nello shift register del MAX7219 con una transizione da livello basso a livello alto del clock (pin CLK – durata minima livello alto 50nS), dopodichè il dato diventa effettivo (eventuale valore da mostrare sul display) con un colpo di clock (basso->alto, durata minima livello alto 50nS) sulla linea di latch (indicata sull’IC come LOAD/CS). La frequenza massima ammessa per il clock è di 10MHz per poter rispettare i periodi minimi di 100nS (50nS alto + 50nS basso).
Mi riferirò al pin di LOAD/CS come ‘Latch’ per abitudine con il 74HC595, dato che il sistema di trasmissione dei dati è praticamente identico. Viene indicato con quel nome perchè normalmente si tiene a livello basso (ecco perchè la sottolineatura alta del CS, che sta per Chip Select) per fare in modo che i dati possano essere memorizzati nello shift register interno, dopodichè si passa a livello alto per “caricare” (LOAD) il dato sui latch di uscita e quindi visualizzarlo.
Modalità di decodifica
Come dicevo, il valore da inviare è a 16 bit ed è così organizzato:
- Bits da 0 a 7: Dato (valore, parametro)
- Bits da 8 a 11: Indirizzo del registro del MAX7219
- Bits da 12 a 15: non utilizzati, possono trovarsi a qualsiasi valore: non vengono mai presi in considerazione.
I registri del MAX7219 sono 14 e in particolare quelli numerati da 1 a 8 servono ad indirizzare i singoli digits del display collegato al MAX7219 (o la singola colonna o comune in una matrice a led 8×8), per cui inviando un valore da 1 a 8 nei bits da 8 a 11, si punta ad uno specifico digit (o colonna) del display: in questo caso il dato (bits 0÷7) rappresenta quali segmenti del digit (o led di una matrice) accendere oppure quale numero visualizzare a seconda della modalità attiva.
Il MAX7219 ha 2 modalità di funzionamento. La modalità di funzionamento più rapida da utilizzare (che non è quella attiva di default) è chiamata Decode. In questa modalità il MAX7219 esegue una decodifica BCD del dato inviato e riporta il numero corrispondente sul digit: questo è il modo più facile da utilizzare in quanto per visualizzare il numero 8, ad esempio, basta inviare come dato il valore 8 e così via. Vediamo un esempio.
Supponiamo di aver attivato la modalità Decode (vedremo dopo come si fa) e di voler visualizzare il numero 5 sul primo digit (il digit 0): invieremo il valore 0x0105: byte alto impostato a 0x01 per dire al MAX7219 che vogliamo scrivere nel primo digit (ovvero quello che normalmente si trova più a destra) e byte basso a 0x05 per indicare che vogliamo visualizzare la cifra ‘5’:
Nell’immagine ho scritto in rosso i bit che non vengono presi in considerazione (e che quindi potrebbero stare pure ad 1). I bits da 12 a 15, come dicevo, non vengono mai presi in considerazione (in nessun caso!), mentre i bits 4,5 e 6 chiaramente non hanno senso solo quando si lavora in modalità decode (BCD), il bit 7, invece, permette di accendere (1) o spegnere (0) il punto decimale del digit selezionato.
Il punto decimale, praticamente, viene gestito sempre così, indipendentemente dalla codifica utilizzata.
In modalità decode è anche possibile visualizzare dei simboli, oltre che le cifre, inviando un dato superiore a 9:
- segno meno/trattino (0x0A)
- lettera E (0x0B)
- lettera H (0x0C)
- lettera L (0x0D)
- lettera P (0x0F)
- digit completamente spento (0x0F)
Sul datasheet del MAX7219, questa decodifica viene chiamata BCD Code B. Ho fatto delle ricerche e non ho trovato “Code B” come qualcosa di standardizzato. Da quanto leggo sul forum EEV, si tratta di un’assunzione propria della Maxim che ha deciso (e direi: giustamente dato che c’era spazio) di includere nella codifica BCD ulteriori simboli che possono tornare utili nelle applicazioni: il segno meno per i numeri negativi e delle lettere per formare la parola HELP ma anche per segnalare alto (H), basso (L), errore (E) o programmazione(?) (P) e alla quale la Maxim ha dato, appunto, il nome Code B.
Tutto questo, ripeto, prevede di aver attivato la modalità decode. Siamo pronti quindi a complicare un po’ di più le cose dopo che abbiamo capito perfettamente il funzionamento base del MAX7219. Diamo uno sguardo alla tabella con l’elenco di tutti registri:
Il registro per la modalità è il 0x09 (0b1001). Inviando in tale registro il valore 0xFF facciamo in modo da lavorare in modalità decode (quella vista fino ad ora), per cui sulla linea seriale, se vogliamo utilizzare la decodifica BCD Code B, invieremo il valore 0x09FF:
Inviando invece il valore ZERO in tale registro (modalità NO decode) abbiamo la possibilità di pilotare i singoli segmenti per ogni digit e possiamo quindi creare anche un nostro font cercando di rappresentare con soli 7 segmenti le lettere dell’alfabeto o simboli, vedremo dopo come fare.
Esistono altre due modalità: inviando oxo1 è possibile lavorare in modalità decode solo per il primo digit e in modalità NO-Decode per i restanti digits e infine, con 0x0F lavoriamo in modalità decode per i primi 4 digits e in no-decode per i restanti 4:
In modalità No-Decode i bits da 0 a 7 (il valore del dato) non verranno più utilizzati per la codifica BCD ma serviranno per accendere (1) o spegnere (0) i singoli segmenti del digit selezionato, per cui il bit 0 corrisponderà al segmento G e così via a ritroso fino al bit 6 che corrisponderà al segmento A e infine il bit 7, come abbiamo già visto, corrisponderà al punto decimale:
Supponiamo di aver attivato la modalità No Decode (abbiamo quindi inviato al MAX7219 il valore 0x0900) e che vogliamo visualizzare la lettera A sul secondo digit (digit 1). Facendo riferimento al disegno sopra, per visualizzare una A dobbiamo accendere tutti i segmenti tranne D e punto, invieremo quindi:
La modalità No Decode è quella attiva di default ed è utilizzata anche quando si pilotano bargraph o matrici di led da 8×8.
Se abbiamo inviato dei dati da visualizzare sui display in modalità Decode e poi, senza cancellare, attiviamo la modalità No Decode (o viceversa), i dati già presenti saranno interpretati con la nuova codifica impostata per cui non è possibile “mischiare” digits impostati con una modalità con digits impostati con un’altra modalità, a meno che non si utilizzino le modalità 0x01 e 0x0F che consentono di impostare modalità miste fisse sui digits come spiegato sopra.
Altri registri
Il registro Intensity (0x0A) permette di regolare l’intensità luminosa. Normalmente l’intensità è controllata tramite una resistenza collegata tra il positivo di alimentazione il pin ISET (è anche possibile collegare un trimmer) e la corrente che scorre nei segmenti sarà pari a 100 volte quella che passa attraverso la resistenza.
Sul datasheet è indicato che una resistenza da 9.53kΩ imposta una corrente dei segmenti pari a 40mA e questo è il valore massimo ammissibile (il valore più vicino è 10kΩ…). Il calcolo della corrente va fatto tenendo conto della tensione di funzionamento del led. Fate riferimento alla tabella 11 del datasheet per la selezione della resistenza più adatta. Ricordo, inoltre, che sulla luminosità influisce non solo la corrente che attraversa i segmenti ma anche la velocità di scansione dei digit che dipende dal numero di digits visualizzati.
Mediante il registro Intensity si può regolare l’intensità luminosa (il duty cycle) in 16 passi rispetto al valore impostato dalla resistenza: si invia un dato da 0 a 15 (viene quindi utilizzato soltanto il nibble basso del valore del dato). All’avvio questo registro si trova a 0, che imposta il display ad una luminosità minima.
Il registro Scan Limit imposta il numero di digits visualizzati, da 1 a 8. Normalmente 8 digits vengono visualizzati con uno scan-rate di 800Hz (il refresh di ogni digit avviene alla frequenza di 100Hz), per cui diminuendo il numero di cifre visualizzate, la luminosità apparirà maggiore perchè il tempo in cui ogni digit rimane accesso è maggiore, per tale motivo questa funzione non dovrebbe essere utilizzata quando si vogliono sopprimere cifre non significative in un numero. Per impostare il numero totale di digits da visualizzare si invia un dato da 0 a 7 (quindi vengono utilizzati solo i primi 3 bit: 0=viene visualizzato solo il digit 0, 1=vengono visualizzati i digits 0 e 1 e così via). All’avvio il registro Scan Limit si trova al valore 0, per cui viene visualizzato solo il primo digit.
Una scelta errata tra resistenza e scan limit può portare ad un guasto sia del display che del MAX7219 per troppa corrente. In particolare se vengono visualizzati da 3 digit a scendere, la situazione si fa ancora più pericolosa, pertanto deve essere diminuita la corrente sui segmenti scegliendo una resistenza più alta. Nel paragrafo Links in basso, su Arduino Playground è presente una discussione su questa questione.
Il registro Shutdown accetta solo due valori: 0=display spento, 1=display acceso. All’accensione il MAX7219 si trova in modalità shutdown, per cui è necessario impostare questo registro a 1 per mostrare il display.
La modalità shutdown serve soltanto a spegnere tutti i digits ma la logica continua a funzionare ugualmente, per cui è possibile inviare dati ai registri o ai digit anche con la modalità shutdown attiva. E’ possibile utilizzare questo registro anche per far lampeggiare tutto il display.
Il registro Display Test accetta solo due valori: 0=modalità di funzionamento normale, 1=test. Il test semplicemente accende accende tutti i led, per cui avendo display a 7 segmenti, si visualizzano tutti 8 col punto decimale acceso. L’attivazione della modalità test sovrascrive le altre impostazioni: ovvero vengono visualizzati comunque tutti gli 8 digits anche se avevamo impostato di visualizzarne di meno. Uscendo dalla modalità test, bisogna reimpostare tutti gli altri registri daccapo.
C’è un ultimo registro: il numero 0 (nessuna operazione = NO OP). Questo registro viene utilizzato soltanto quando si collegano più MAX7219 in cascata per evitare di inviare dati agli integrati a cui non serve. Faccio un esempio: supponiamo di avere 4 MAX7219 in cascata e necessitiamo di inviare i dati soltanto a quello posto più a sinistra: invieremo 3 NO OP seguiti dal valore a 16 bit: I NO OP scorreranno verso destra raggiungendo il display più a destra e così via, fino al quarto dato, diverso da NO OP, che rimarrà nel quarto display (il primo nella catena di trasmissione, quello più a sinistra).
Inizializzazione
Dato che abbiamo visto che alcuni registri si trovano in una precisa modalità all’avvio, sarà necessario inviare i seguenti comandi:
- Uscire eventualmente dalla modalità test.
- Impostare il numero di digits da visualizzare nel registro Scan Limit (0x0B) – Valore da 0 (per far accendere un solo digit) a 7 (per tutti e 8). Ricordo che questo valore ha delle criticità in quanto va rapportato alla resistenza di limitazione per evitare di bruciare display e MAX7219.
- Impostare la modalità di decodifica (registro 0x09) : Usare uno dei 4 valori consentiti (in particolare 0=no decode, 0xFF=codifica BCD “code B”)
- Regolare l’intensità luminosa (registro 0x0A) – Valore da 0x00 (minima luminosità) a 0x0F
- Impostare il registro shutdown (0x0c) : 1 per visualizzare il display.
L’impostazione del registro shutdown ci mette almeno 250µS per essere effettiva, quindi dopo aver impostato per ultimo tale registro, bisogna attendere almeno questo tempo prima di eseguire ulteriori operazioni.
Nell’articolo successivo ho illustrato una libreria che ho scritto per il MAX7219 da utilizzare con i microcontrollori Microchip PIC per sfruttare display 7 segmenti.
Links e Downloads
- Datasheet MAX7219 (296 download)
- Acquisto display ad 8 digits con MAX7219 su Futura Elettronica
- Acquisto display ad 8 digits con MAX7219 su Amazon
- Arduino Playground – Il MAX7219
- Libreria MAX7219 per Microcontrollori Microchip PIC