
I progettisti di sistemi embedded oggi devono affrontare le richieste sempre più massicce di interfacciamento fra l’uomo e le macchine. Queste esigenze si riflettono nel sempre maggior impiego di sistemi quali LCD alfanumerici, custom e TFT. Ecco dunque come approcciare dal punto di vista tecnico queste tecnologie.
La visualizzazione delle informazioni è praticamente una delle caratteristiche più richieste in tutti i settori delle applicazioni elettroniche, come industriale, consume9r, medicale, telecom. Molteplici sono le tipologie di interfaccia HID (Human Interface Devices) che consentono alle macchine di fornire all’esterno informazioni intellegibili dalle persone. A partire dai ben noti display a segmenti led, riportati in figura 1, attraverso i quali è possibile visualizzare le sole cifre numeriche ed eventualmente il punto per i decimali, si passa agli ormai diffusissimi display alfanumerici 16x2, ovvero 16 caratteri per due righe.

Figura 1: display a 7 segmenti
Questi display sono abitualmente disponibili in due formati, con chip di controllo a bordo oppure senza. Nel primo caso, il chip può esser montato su un piccolo stampato che supporta anche il vetro (è il caso del COB, o Chip On Board, rappresentato in figura 2) oppure sul vetro stesso (COG, ossia Chip On Glass).

Figura 2: LCD 16x2 COB.
Chiaramente la scelta dipende dal tipo di applicazione e dal costo che si vuol dedicare al display (un chip on glass costa più di un chip on board). Oltre a questi dispositivi, esiste la possibilità di realizzare un display che invece di utilizzare caratteri e cifre, abbia delle icone realizzate secondo un particolare disegno e secondo ben determinate specifiche. E’ questo il caso dei display LCD custom. Spesso questi dispositivi vengono utilizzati laddove ci siano informazioni complesse da visualizzare, oppure dove l’aspetto estetico della grafica risulta determinante per il prodotto. Si pensi ad esempio ad un cronotermostato ambientale, che deve rappresentare la temperatura ambiente, ma che necessita anche di piccole icone per raffigurare i giorni della settimana ecc... Chiaramente, i costruttori di LCD devono realizzare delle maschere particolari, per cui il costo di un LCD customizzato è molto maggiore di un alfanumerico. Investimenti di questo tipo sono dunque realizzati solo quando le quantità produttive sono molto elevate. Per finire, la riduzione del costo della tecnologia ha reso oggi disponibili in misura sempre maggiore le tecnologie di display a matrice attiva. Questi oggetti, come suggerisce il nome, trasmettono la luce attraverso delle matrici di transitor. Il risultato è una immagine più nitida e luminosa, a partià di dimensioni. Anche i consumi sono molto ridotti, ragion per cui queste nuove tecnologie sono sicuramente preferibili a quella LCD. Chiaramente i costi sono decisamente maggiori, anche se nell’ultimo anno le cose sono cambiate, dal momento che un numero sempre maggiore di applicazioni utilizzano questa tecnologia, con conseguente riduzione dei costi. Questi oggetti si presentano come matrici di punti (pixel) in grado riprodurre un numero di colori molto elevato (da 256 sino a 65 mila). Grazie a queste combinazioni di colori, si è in grado di riprodurre in maniera assolutamente definita la maggior parte delle immagini, con rese qualitative eccezionalmente superiori rispetto alla tecnologia LCD. A titolo di esempio si veda figura 3.

Figura 3: TFT su board Microchip.
La proposta tecnica Microchip
Microchip fornisce microcontrollori ed integrati analogici che aiutano il progettista ad interfacciarsi con ognuno dei display citati in precedenza. In particolare, la famiglia 16F91X è la soluzione a più basso costo per implementare visualizzazione su un micro ad 8 bit. La famiglia consta di 4 devices, PIC16F913, PIC16F914, PIC16F916, PIC16F917, che si differenziano per pin count, taglio di memoria e soprattutto per numero massimo di segmenti LCD pilotabili. In figura 4 un piccolo specchietto che riassume le caratteristiche dei devices citati.

Figura 4: famiglia PIC16F91x.
Questi oggetti, avendo a bordo un “LCD Driver Module” sono in grado di generare direttamente la sequenza di controllo nei tempi corretti, in modo da poter pilotare LCD senza controller a bordo in maniera statica o multiplexata. La differenza fra queste due modalità consiste nel pilotare staticamente ogni singolo segmento del LCD, dando così origine ad una accensione persistente del pixel-segmento, oppure nell’accendere a turno i vari segmenti del LCD secondo una logia di tipo matriciale, facendo in modo che la frequenza di pilotaggio rimanga sempre superiore alla frequenza minima chiamata di “persistenza retinica”, pari a circa 16Hz. Basandosi infatti sullo studio effettuato da Roget oltre un seccolo fa, si è dimostrato che se si sottopone una immagine pulsante all’occhio umano con frequenza di pulsazione maggiore dei 30 Hertz, l’occhio umano non percepisce sfarfallii. Per questo motivo è quindi possibile pilotare un numero elevato di segmenti facendo uso di pochi pin dedicati al pilotaggio (funzione riga) e di alcuni altri dedicati alla selezione di alcune regioni (funzione colonna). Proprio per questo motivo, i microcontrollori di questa famiglia sono costituti da un controllore dei tempi che, interfacciandosi sul DATA bus, raccoglie le informazioni di multiplexing desiderato e, combinando le proprie informazioni di tempo con le informazioni di segmento contenute nei registri LCDDATAx, genera un insieme di segnali che vanno a comporre la matrice di informazione per l’accensione o lo spegnimento dei vari segmenti dell’LCD da pilotare. In figura 5 si riporta lo schema a blocchi della periferica LCD Driver dei PIC in esame.

Figura 5: Block Diagram famiglia PIC16F91x.
Prendendo ad esempio il modello PIC16F913, potremo pilotare staticamente solo16 segmenti, ma se passiamo ad un pilotaggio in multiplexing 1/2, avremo un massimo di 32 segmenti. Utilizzando invece un multiplexing 1/3 avremo ben 48 segmenti pilotabili. Per finire, il massimo multiplexing supportato dalla famiglia è di 1/4, attraverso il quale si potranno pilotare, sempre con lo stesso microcontrollore, ben 60 segmenti, ossia più del triplo degli effettivi PIN del micro stesso! (28 pin). In figura 6 una schematizzazione di queste informazioni.

Figura 6: tabella multiplexing - segmenti.
Dal punto di vista pratico, questi multiplexing si traducono anche in un trade-off della potenza inviata all’LCD nell’unità di tempo, che si riflette in un contrasto meno spiccato nel medeismo LCD in caso di pilotaggio in Multiplexing. A questo proposito esiste un parametro, chiamato “Discrimination Ratio” (d’ora in avanti menzionato come D), che fornisce una indicazione della tensione (Von/Voff). Dal momento che nel caso ottimo, ossia nel caso di pilotaggio statico, si ha una Voff di 0 ed una Von di 1, il D è pari ad infinito. A tale proposito si veda figura 7.

Figura 7: Discrimination Ratio nel caso di pilotaggio statico
Per quanto riguarda invece, ad esempio, un multiplexing di ½, le tensioni da portare al LCD per fornire tutte le informazioni sono fornite attraverso tre diverse tensioni. La tensione efficace nel caso di pixel acceso è di 1,58 Volt, mentre nel caso di pixel spento è di 1 Volt. Per questo motivo il D vale 1,58. In figura 8 e 9 lo studio di questo caso. Microchip, attraverso una dettagliata analisi dei bias di tensione in funzione dei mux desiderati, fornisce una tabella descrittiva dei diversi valori di Discrimination Ratio, dando origine ad una interessante osservazione.

Figura 8: caso di pixel ON con 1/2 MUX.

Figura 9: caso di Pixel Off con MUX 1/2 e conseguente D ratio.
Laddove possibile, è preferibile utilizzare una polarizzazione di 1/3, al fine di ottimizzare il contrasto finale del LCD che si andrà a pilotare. A tal fine si veda figura 10.

Figura 10: tabella del Discrimintaion Ratio in funzione
di Bias e MUX.

Figura 11: gestione dei segmenti.
I data sheet della famiglia PIC16F91x sono altresì corredati di tabelle indicative delle abbinate COMSEG da utilizzare nel pilotaggio di LCD compositi. Abitualmente, i fornitori di LCD forniscono una analoga tabella, che consente di “comporre” correttamente la matrice abbinando i singoli segmenti da pilotare alle accoppiate COM-SEG del microcontrollore. A volte, nei modelli più “pregiati”, si ha anche una rappresentazione grafica delle connessioni dei singoli segmenti verso l’esterno, per avere anche una idea di quali abbinare ottimizzando il microcontrollore al fine di ottenere una strategia di multiplexing ottima. Per finire, si riporta all’attenzione del lettore una routine complessa (listato 1) attraverso la quale sarà possibile pilotare un LCD di tipo alfanumerico, facendo uso del device PIC16F913.
list p=16F913 #include P16F913.inc ; LCD data bits #define LCD_D4 PORTD, 0 #define LCD_D5 PORTD, 1 #define LCD_D6 PORTD, 2 #define LCD_D7 PORTD, 3 ; LCD data bits #define LCD_D4_DIR TRISD, 0 #define LCD_D5_DIR TRISD, 1 #define LCD_D6_DIR TRISD, 2 #define LCD_D7_DIR TRISD, 3 ; LCD E clock #define LCD_E PORTA, 1 ; LCD read/write line #define LCD_RW PORTA, 2 ; LCD register select line #define LCD_RS PORTA, 3 #define LCD_E_DIR TRISA, 1 #define LCD_RW_DIR TRISA, 2 #define LCD_RS_DIR TRISA, 3 #define LCD_INS 0 #define LCD_DATA 1 D_LCD_DATA UDATA 0x20 COUNTER res 1 delay res 1 temp_wr res 1 temp_rd res 1 GLOBAL temp_wr PROG1 CODE ;***************************** LCDLine_1 banksel temp_wr movlw 0x80 movwf temp_wr call i_write return GLOBAL LCDLine_1 LCDLine_2 banksel temp_wr movlw 0xC0 movwf temp_wr call i_write return GLOBAL LCDLine_2 d_write ;write data call LCDBusy bsf STATUS, C call LCDWrite banksel TXREG ;move data into TXREG movwf TXREG banksel TXSTA ;wait for data TX btfss TXSTA,TRMT goto $-1 banksel PORTA return GLOBAL d_write i_write ;write instruction call LCDBusy bcf STATUS, C call LCDWrite return GLOBAL i_write rlcd macro MYREGISTER IF MYREGISTER == 1 bsf STATUS, C call LCDRead ELSE bcf STATUS, C call LCDRead ENDIF endm ;****************************** LCDInit clrf PORTA ;configure control lines banksel TRISA bcf LCD_E_DIR bcf LCD_RW_DIR bcf LCD_RS_DIR movlw b’00001110’ banksel ADCON1 movwf ADCON1 ; Wait ~15ms @ 20 MHz movlw 0xff banksel COUNTER movwf COUNTER movlw 0xFF banksel delay movwf delay call DelayXCycles decfsz COUNTER, F goto $-3 ;#1 Send control sequence movlw b’00110000’ movwf temp_wr bcf STATUS,C call LCDWriteNibble movlw 0xff ;Wait ~4ms@20 MHz movwf COUNTER movlw 0xFF movwf delay call DelayXCycles decfsz COUNTER, F goto $-3 ;#2 Send control sequence movlw b’00110000’ movwf temp_wr bcf STATUS,C call LCDWriteNibble movlw 0xFF ;Wait ~100us@20 MHz movwf delay call DelayXCycles ;#3 Send control sequence movlw b’0011000’ movwf temp_wr bcf STATUS,C call LCDWriteNibble ;test delay movlw 0xFF ;Wait ~100us@20 MHz movwf delay call DelayXCycles ;#4 set 4-bit movlw b’00100000’ movwf temp_wr bcf STATUS,C call LCDWriteNibble call LCDBusy ;Busy? movlw b’00101000’ movwf temp_wr call i_write ;#6 Display = ON movlw b’00001101’ movwf temp_wr call i_write ;#7 Display Clear movlw b’00000001’ movwf temp_wr call i_write ;#8 Entry Mode movlw b’00000110’ movwf temp_wr call i_write ;DDRAM addresss 0000 movlw b’10000000’ movwf temp_wr call i_write ;return home ; movlw b’00000010’ ; movwf temp_wr ; call i_write return GLOBAL LCDInit ; ***************************** LCDWriteNibble btfss STATUS, C bcf LCD_RS btfsc STATUS, C bsf LCD_RS bcf LCD_RW banksel TRISD bcf LCD_D4_DIR bcf LCD_D5_DIR bcf LCD_D6_DIR bcf LCD_D7_DIR NOP ; Small delay NOP banksel PORTA bsf LCD_E ; Set high nibble btfss temp_wr, 7 bcf LCD_D7 btfsc temp_wr, 7 bsf LCD_D7 btfss temp_wr, 6 bcf LCD_D6 btfsc temp_wr, 6 bsf LCD_D6 btfss temp_wr, 5 bcf LCD_D5 btfsc temp_wr, 5 bsf LCD_D5 btfss temp_wr, 4 bcf LCD_D4 btfsc temp_wr, 4 bsf LCD_D4 NOP NOP bcf LCD_E ; Send the data return ; ***************************** LCDWrite call LCDWriteNibble BANKSEL temp_wr swapf temp_wr, f call LCDWriteNibble banksel temp_wr swapf temp_wr,f return GLOBAL LCDWrite ; ***************************** ; LCDRead banksel TRISD ; Set data bits to inputs bsf LCD_D4_DIR bsf LCD_D5_DIR bsf LCD_D6_DIR bsf LCD_D7_DIR BANKSEL PORTA ; Set the register select btfss STATUS, C bcf LCD_RS btfsc STATUS, C bsf LCD_RS bsf LCD_RW ;Read = 1 NOP NOP ; Setup to clock data bsf LCD_E NOP NOP NOP NOP ; Get high nibble btfss LCD_D7 bcf temp_rd, 7 btfsc LCD_D7 bsf temp_rd, 7 btfss LCD_D6 bcf temp_rd, 6 btfsc LCD_D6 bsf temp_rd, 6 btfss LCD_D5 bcf temp_rd, 5 btfsc LCD_D5 bsf temp_rd, 5 btfss LCD_D4 bcf temp_rd, 4 btfsc LCD_D4 bsf temp_rd, 4 ; Finished reading the data bcf LCD_E NOP NOP NOP NOP NOP NOP NOP NOP ; Setup to clock data bsf LCD_E NOP NOP btfss LCD_D7; Get low nibble bcf temp_rd, 3 btfsc LCD_D7 bsf temp_rd, 3 btfss LCD_D6 bcf temp_rd, 2 btfsc LCD_D6 bsf temp_rd, 2 btfss LCD_D5 bcf temp_rd, 1 btfsc LCD_D5 bsf temp_rd, 1 btfss LCD_D4 bcf temp_rd, 0 btfsc LCD_D4 bsf temp_rd, 0 ; Finished reading the data bcf LCD_E FinRd return ; ***************************** LCDBusy ; Check BF rlcd LCD_INS btfsc temp_rd, 7 goto LCDBusy return GLOBAL LCDBusy ; ***************************** DelayXCycles decfsz delay, F goto DelayXCycles return ; ***************************** END
Listato 1 |
