Home

Il teschio dei pirati

I PICMicro e i display LCD alfanumerici (parte 2)

Dopo aver visto, nel primo articolo di questa serie sugli LCD, le caratteristiche dei display alfanumerici attrezzati con il controller HD44780 di Hitachi, si prosegue con le modalità di interfacciamento e di comando.

La modalità a 4 bit

Il controller HD44780 permette l'interfacciamento tra LCD e microcontrollore con un databus a 4 bit oppure a 8 bit. Al fine di limitare il numero dei pin del microcontrollore impegnati sul comando del display, in questo articolo si è preferito adottare la modalità a 4 bit, secondo lo schema seguente.

 

Schema elettrico

Per poter comandare il display, è importante agire tanto sul databus quanto sui bit di controllo: E, RS, R/W. Il controller HD44780 necessita di una ben precisa sequenza di comandi e di dati, con tempistiche da rispettare "alla lettera", pena il mancato funzionamento del progetto. Il flow chart del setup è illustrato in figura.

 

Flow chart

Un estratto del codice C che esegue quanto indicato, è il seguente:

 

void LCD_Init (void)
{
        char k;

        Delay_ms(5);

// Reset Sequence
        LCD_EN = 0;
        LCD_RS = 0;
        LCD_RW = 0;

        for (k=1;k<=3;k++)
        {
            LCD_DB4 = 1;
            LCD_DB5 = 1;
            LCD_DB6 = 0;
            LCD_DB7 = 0;

            LCD_EN_Strobe();

            Delay_ms(5);
        }
        PORTB = 0x00;

//Four bit mode

        LCD_DB4 = 0;
        LCD_DB5 = 1;
        LCD_DB6 = 0;
        LCD_DB7 = 0;

        LCD_EN_Strobe();

// 4-bit mode, 2 lines display, font 5x8 pixels

        LCD_SendCommand(0x28);


// Increment, no shift

        LCD_SendCommand(0x06);

// Display ON, Cursor OFF, Blink OFF

        LCD_SendCommand(0x0C);
        LCD_SendCommand(0x01);
        LCD_SendCommand(0x03);
      
}


Per inviare un comando al display, è necessario avere RS ed R/W entrambi a valore 0 ed inviare prima il nibble più basso e poi il nibble più alto. Ciascun invio deve essere seguito da uno strobe di E che deve eseguire la transizione basso-alto-basso.

 

I comandi

Il display accetta, oltre alla fase di inizializzazione, anche altri comandi; alcuni di essi deveono essere seguiti da un dato. Un comando e un parametro differiscono solamente per il fatto che quando si inviano comandi RS vale 0, invece quando si inviano dati RS vale 1.

// Sends command to LCD
void LCD_SendCommand(char Command)
{
        LCD_RS = 0;
        LCD_SendByte(Command);
}

// Sends data to LCD
void LCD_SendData(char Data)
{
        LCD_RS = 1;
        LCD_SendByte(Data);
}

 

I comandi che possono essere inviati al display sono riassunti in questa tabella.

Tabella comandi

 

Caratteri speciali programmabili

Ogni display ha a disposizione un set di caratteri piuttosto ampio. In figura è riportato un set tratto da un datasheet.

Tabella dei caratteri

Ora, ciascun carattere rispecchia (quasi) interamente la tabella ASCII ma, come si può notare, sono disponibili anche caratteri non latini, alcuni simboli greci ed alcuni simboli che si rifanno ad alfabeti orientali. Il controller HD44780 permette la memorizzazione di alcuni caratteri definiti dall'utente, fino ad un massimo di 8 caratteri. Il gioco è piuttosto semplice: si parte da una matrica 5x8 pixel (questa è la dimensione "classica" di un carattere):

 

A questo punto si inizia ad oscurare ciascun pixel dando forma al carattere che vogliamo. Nell'esempio che segue è riportato un ombrellino

 

Ombrellino

Per ogni riga, si calcola il valore che emerge dalla colorazione dei pixel, secondo un semplice calcolo in potenza di 2, considerando il pixel meno significativo quello a destra. In questo modo è possibile costruirsi caratteri e simboli altrimenti non disponibili.

Le memorizzazione dei caratteri speciali avviene scrivendoli in un'area della memoria RAM del display, a partire dall'indirizo 0x40, infatti, ha sede la CGRAM, Charachter Generator RAM. Un comando di scrittura all'indirizzo desiderato, seguito dagli otto byte che costituiscono il carattere. Uno stralcio di codice è il seguente:

 

void LCD_PutCGRAMCharPos (char* GraphicChar, char DisplayPosition)
{
    char count;

    LCD_SendCommand (0x40+8*DisplayPosition);
    for (count = 0; count<=7; count++)
    {
        LCD_PutChar(GraphicChar[count]);
    }
}

 

Benché 8 caratteri possono sembrare pochi, questo vincolo non deve scoraggiare e può essere abilmente aggirato, avendo cura di raggruppare insiemi di 8 caratteri in modo omogeneo. Nel video che segue è mostrato come, oltre ai caratteri già disponibili si possano disegnare e rappresentare simboli diversi, molto più che 8.

Ho voluto preparare una semplice applicazione per OpenOffice Calc, grazie alla quale è possibile creare i caratteri custom e poi utilizzarli nel proprio codice. L'applicazione calcola automaticamente i valori dei byte da inviare alla CGRAM del display.

pplicazione OpenOffice Calc per i simboli personalizzati

 

Ed ecco alcune immagini che ho realizzato:

Simboli personalizzati (1)

Simboli personalizzati (1)

 

Simboli personalizzati (2)

Simboli personalizzati (2)

Simboli personalizzati (3)

Simboli personalizzati (3)

 

Un microcontrollore PIC "stilizzato"

Un microcontrollore PIC "stilizzato"

Il teschio dei pirati

Il teschio dei pirati

Firmware

Il codice per pilotare il display l'ho scritto in linguaggio C. Si sa, il C è portabile e questo aspetto è fondamentale quando si vuole compilare il progetto con compilatori diversi oppure "portarlo" su altre piattaforme hardware. Avrei potuto utilizzare un PIC18 ed usare C18, ma dato che i PIC16 sono ancora molto richiesti, ho preferito utilizzare SDCC, stavolta "mettendolo alla prova" con un compito più significativo che non quello semplice di accendere un LED. Ecco uno stralcio delle funzioni che ho implementato:

extern void LCD_Init (void);
extern void LCD_GotoXY (unsigned char, unsigned char);
extern void LCD_PutCharXY (unsigned char, unsigned char, unsigned char);
extern void LCD_PutChar (unsigned char);
extern void LCD_PutStringXY (unsigned char, unsigned char, char* );
extern void LCD_PutString (char*);
extern void LCD_EN_Strobe (void);
extern void LCD_SendCommand(char);
extern void LCD_SendData(char);
extern void LCD_SendByte (char);
extern unsigned char LCD_read_byte (void);
extern void LCD_PutCGRAMCharPos (char*, char );
extern void LCD_Clear (void);
extern void nop (void);
extern void Delay_ms (unsigned int);

The "pirate display"

Ed ecco qui, il risultato di quanto illustrato in questi due articoli. La demo mostra l'utilizzo del display con un PIC16F876A, qualche carattere personalizzato e...

File download

Il codice è scaricabile dal mio sito PICexperience.it, al seguente link. Il pacchetto zip contiene i seguenti file:

  •     DemoLCD.c: il firmware che si vede in esecuzione nel video;
  •     LCD.c: funzioni di gestione LCD;
  •     LCD.h: file di include che contiene i prototipi di funzione;
  •     Make.bat: file da lanciare su sistemi MS-Windows per compilare con SDCC il firmware;
  •     CustomChar_LCDDisplay.ods: applicazione OpenOffice Calc per la determinazione dei simboli personalizzati.

 

Licenza

Questo articolo ed il software rilasciato rientrano 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)
Creative Common License Note legali (italiano)
  Legal Code (international)
  Commons deed (international)

 

Biblografia

Licenza Creative Commons
Questa opera viene distribuita con licenza Creative Commons Attribuzione - Non commerciale - Non opere derivate 3.0 Unported.
ShoppingASEhandelASErhvervIndexDKServiceIndexDK