Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

14
voti

LO HAI MAI REALIZZATO CON UN PIC? - I PICMicro e i display grafici (seconda parte)

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.

Diagramma di timing per la lettura (READ)

Diagramma di timing per la lettura (READ)

Diagramma di timing per la scrittura(WRITE)

Diagramma di timing per la scrittura(WRITE)

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:

Suddivisione del display in lati e pagine

Suddivisione del display in lati e pagine

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:

Demo: disegno di punti su display grafico

Demo: disegno di punti su display grafico

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.

Licenza Creative Commons

Licenza Creative Commons

Sintesi delle note legali (italiano)

Note legali (italiano)

Legal code (international)

Commons deed (international)

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

8

Commenti e note

Inserisci un commento

di ,

Grazie anche a te Luca1995. Il tipo uint8_t deriva dalle raccomandazioni di MISRAC e indica un intero a 8 bit senza segno. In sostanza, per i PIC, è un unsigned char.

Rispondi

di ,

Grande articolo mi ha salvato :) Volevo solo chiederti.....ma che formato è uint8_t nelle funzioni?

Rispondi

di ,

Grazie, mir!

Rispondi

di ,

Pic, ovvero P come Paolino, eccellente. Grazie.

Rispondi

di ,

Grazie a te, DADO91.

Rispondi

di ,

Paolino sempre una garanzia! Grazie per i tuoi articoli e per l'aiuto sul forum! Grande!

Rispondi

di ,

Too good, Carlo. Grazie.

Rispondi

di ,

Paolo, è come leggere un libro. Complimenti, -carlo.

Rispondi

Inserisci un commento

Per inserire commenti è necessario iscriversi ad ElectroYou. Se sei già iscritto, effettua il login.