Dopo aver visto la struttura di un display grafico con controller KS0108, si passa ora alla descrizione delle operazioni utili all'accesso al display, per inviare comandi e dati e per leggere valori di stato e dati. Queste operazioni avvengono grazie ai segnali di controllo ed al bus parallelo, tramite i quali è possibile il dialogo tra microcontrollore e display.Le informazioni (istruzioni) che tranistano sul bus vengono quindi suddivisi in due categorie: scrittura e lettura. Ciascuna categoria contiene comandi e dati da e per il display. Si tratta di inviare e ricevere pacchetti a 8 bit, impiegnado tutto il bus parallelo.
Indice |
I diagrammi di timing
Per pilotare correttamente il display i segnali devono seguire delle precise sequenze e temporizzazioni. Nel datasheet del controller sono riportati i valori dei tempi minimi e massimi da rispettare per ciascun segnale (si raimanda alla lettura del datasheet per approfondimenti). Le sequenze, invece, più facilmente individuabili nel codice seorgente del micro che va ad interfacciarsi col display, vengono riportate nelle figure seguenti. Si tratta delle sequenze da rispettare per la scrittura e la lettura di dati e comandi.
Le istruzioni
Il controller KS0108 mette a disposizione alcune istruzioni di base con le quali crearsi delle proprie funzioni per l'accesso al display. In tabella sono riportate le istruzioni con i relativi valori dei singoli segnali.
Istruzione | R/S | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | Funzione |
---|---|---|---|---|---|---|---|---|---|---|---|
Display OFF | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | Spegne il display |
Display ON | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | Accendeil display |
Set Address | 0 | 0 | 0 | 1 | X5 | X4 | X3 | X2 | X1 | X0 | Imposta la coordinata X (0...63) |
Set Page | 0 | 0 | 1 | 0 | 1 | 1 | 1 | Y2 | Y1 | Y0 | Imposta la pagina (0...7) |
Display Line Start | 0 | 0 | 1 | 1 | L5 | L4 | L3 | L2 | L1 | L0 | Imposta la prima linea di visualizzazione (0...63) |
Status Read | 0 | 1 | Busy | 0 | ON/OFF | RESET | 0 | 0 | 0 | 0 | Lettura byte di stato |
Write display data | 1 | 0 | Data_7 | Data_6 | Data_5 | Data_4 | Data_3 | Data_2 | Data_1 | Data_0 | Scrittura dati in cella RAM del display |
Read display data | 1 | 1 | Data_7 | Data_6 | Data_5 | Data_4 | Data_3 | Data_2 | Data_1 | Data_0 | Lettura dati dalla cella RAM del display |
Come si può notare, alcune istruzioni accettano "parametri", come ad esempio l'impostazione della coordinata X o la scelta della pagina. vale allora la pena di prepararsi alcune macro che permetteranno poi di aggiungere la parte parametrica, senza troppe difficoltà:
#define DISPLAY_ON 0x3F #define DISPLAY_OFF 0x3E #define SET_X 0x40 #define SET_PAGE 0xB8 #define DISPLAY_START_LINE 0xC0
Implementazione in C delle funzioni di base
Prima di arrivare a tracciare sul display punti, linee, curve ed altro ancora è bene fare il punto sulle funzionalità di base, che formeranno il substrato per le funzioni successive. Alcune di queste funzioni si possono desumere facilmente dal datasheet, mentre altre torneranno utili in futuro. Per semplicità, il codice mostrato è scritto con C18 di Microchip e mostra alcune delle funzioni implementate. Lo schema elettrico di partenza è quello che già ho indicato nell'articolo precedente:
I segnali di controllo ed il databus sono identificati come nel seguito:
/* Display connections */ #define GLCD_DataPort LATB #define GLCD_ReadDataPort PORTB #define GLCD_DataPortDirection TRISB #define GLCD_CS1 LATDbits.LATD2 #define GLCD_CS2 LATDbits.LATD3 #define GLCD_RS LATDbits.LATD4 #define GLCD_RW LATDbits.LATD5 #define GLCD_RST LATDbits.LATD6 #define GLCD_EN LATDbits.LATD7 #define GLCD_CS1_Direction TRISDbits.TRISD2 #define GLCD_CS2_Direction TRISDbits.TRISD3 #define GLCD_RS_Direction TRISDbits.TRISD4 #define GLCD_RW_Direction TRISDbits.TRISD5 #define GLCD_RST_Direction TRISDbits.TRISD6 #define GLCD_EN_Direction TRISDbits.TRISD7
Una volta fissate le modalità di collegamento del micro con il display, si passa alla stesura delle funzioni di inizializzazione del display.Vengono imposti gli stati di tristate e il display viene acceso, impostando pagine e colonne di ciascun lato del display.
void GLCDInit (void) { GLCD_DataPortDirection = 0x00; GLCD_CS1_Direction = 0; GLCD_CS2_Direction = 0; GLCD_RS_Direction = 0; GLCD_RW_Direction = 0; GLCD_RST_Direction = 0; GLCD_EN_Direction = 0; GLCD_DataPort = 0; GLCD_ON(); } void GLCD_ON (void) { GLCD_RST = 1; GLCDWriteCommand(GLCD_LEFT, DISPLAY_ON); GLCDWriteCommand(GLCD_RIGHT, DISPLAY_ON); GLCDWriteCommand(GLCD_LEFT, SET_X); GLCDWriteCommand(GLCD_RIGHT, SET_X); GLCDWriteCommand(GLCD_LEFT, SET_PAGE); GLCDWriteCommand(GLCD_RIGHT, SET_PAGE); DisplayStartLine(GLCD_LEFT, DISPLAY_START_LINE); DisplayStartLine(GLCD_RIGHT, DISPLAY_START_LINE); }
L'accesso in scrittura, come detto, può avvenire tanto per impartire comandi quanto per trasferire dati, è sufficiente avere cura di impostare correttamente il segnale RS:
void GLCDWriteCommand (uint8_t side, uint8_t DataByte) { GLCD_RS = 0; GLCDWrite(side, DataByte); } void GLCDWriteByte (uint8_t side,uint8_t DataByte) { GLCD_RS = 1; GLCDWrite(side, DataByte); }void GLCDWrite (uint8_t side, uint8_t WriteData) { GLCD_EN = 0; GLCD_RW = 0; if (side == GLCD_LEFT) { GLCD_CS1 = 0; GLCD_CS2 = 1; } else if (side == GLCD_RIGHT) { GLCD_CS1 = 1; GLCD_CS2 = 0; } GLCD_DataPort = WriteData; ENStrobe(); GLCD_RS = 0; }
La gestione dei segnali è sincrona con segnale di Enable, pertanto una funzione da non dimenticarsi di scrivere è quella che esegue lo strobe di Enable
void ENStrobe (void) { GLCD_EN = 1; Nop(); GLCD_EN = 0; }
La suddivisione del display in lati (destro e sinistro) e pagine è rappresentata nella seguente fotografia:
Facciamo il punto
Ora che le funzioni di base sono state preparate si passa a disegnare. Le primitive geometriche come la retta (sarebbe meglio dire "segmento") ed il cerchio sono definite come luogo dei punti. Pertanto, il primo elemento da tracciare su display è il singolo punto. Per tracciare un punto sullo schermo sono necessari:
- coordinata X del punto;
- coordinata Y del punto;
- colore del punto.
Dato che si tratta di un display monocromatico, il colore non sarà altro che una variabile che potrà assumere valore 1 per indicare che il punto va disegnato e 0 per cancellarlo. La funzione che traccia il punto è la seguente:
void GLCD_Dot(uint8_t xPos,uint8_t yPos, uint8_t color) { uint8_t Col_Data, DataRead; GLCD_GotoXY(xPos,yPos); if (xPos<64) { GLCD_CS1 = 0; GLCD_CS2 = 1; } else { GLCD_CS1 = 1; GLCD_CS2 = 0; } GLCDRead(xPos); DataRead = GLCDRead(xPos); if (color>0) { Col_Data = (1<<(yPos%8)) | DataRead; //Put dot } else { Col_Data = ~(1<<(yPos%8)) & DataRead; //Clear dot } GLCD_GotoXY(xPos,yPos); GLCD_EN = 0; GLCD_RW = 0; GLCD_RS = 1; GLCD_DataPort = Col_Data; ENStrobe(); GLCD_RS = 0; }
La funzione porta il focus alla posizione (xPos, Ypos), determina se il punto va disegnato sul lato destro o sinistro del display, poi legge il valore del byte di RAM del display a cui appartiene il punto in oggetto e finalmente lo disegna. La tracciatura dei punti sul display porta al risultato mostrato in questa fotografia:
Linee, cerchi, bitmap...
Ritengo che di carne al fuoco ce ne sia a sufficienza per il momento e lascio al lettore il tempo di digerire quanto proposto. Nel prossimo articolo mostrerò come sia possibile disegnare linee, cerchi, quadrati e rettangoli, ma anche importare file bitmap e scrivere testi. Tutto ciò per avere a disposizione un ampio set di istruzioni e funzioni per avere iltotale controllo del display.
Licenza
Questo articolo rientra nell'ambito della licenza CREATIVE COMMONS BY-NC-ND Italia 3.0, secondo quanto indicato nelle note legali qui riportate.
Sintesi delle note legali (italiano)
Ogni riferimento a marchi di terze parti si è reso necessario esclusivamente per dare senso a questo articolo. I marchi citati appartengono alle aziende proprietarie.
Biblografia
- Sito web PicExperience