DISPLAY GRAFICO PER ATMEL AVR AT90S8515


Se avete realizzato il kit di sviluppo per l’Atmel AT90S8515  o utilizzate questo microcontrollore per una vostra applicazione specifica,  perche’ non dotare  il circuito di un display grafico LCD ?

 In questo articolo, oltre ad analizzare  le  funzioni,  le istruzioni ed i comandi  per il controllo dei display grafici basati sul microcontrollore Toshiba T6963, propongo la realizzazione di un’interfaccia che permetta di minimizzare le linee di I/O impegnate dal microcontrollore per colloquiare con l’LCD.  L’articolo e’, inoltre, corredato di un driver  firmware scritto in particolare per l’AVR AT90S8515.

Introduzione

La diffusione dei display a cristalli liquidi (LCD) ha subìto in questi anni un aumento vertiginoso; dai monitor dei Personal Computer ai telefoni cellulari oramai non c’e’ apparato elettronico o elettrodomestico che non sia dotato di un display lcd su cui visualizzare regolazioni e dati per l’utilizzatore.

Per delle semplici realizzazioni “fai da te” si possono attualmente reperire, con sempre maggiore facilita’, anche se con prezzi ancora piuttosto elevati, modelli di lcd grafici monocromatici che sono facili da gestire con un microcontrollore.

La scelta di un lcd grafico monocromatico e’ determinata principalmente dal chip che rende “intelligente” il modulo, cioe’ che si “interpone” tra il microcontrollore e la matrice a cristalli liquidi, occupandosi di fornire l’alimentazione, di effettuare il rinfresco dei pixel etc... Alcuni modelli includono anche un generatore interno di caratteri ascii o permettono altre funzioni particolari. Quello che rimane da fare al nostro microcontrollore e’ instaurare un colloquio con il controller del modulo fornendogli i comandi e le informazioni da visualizzare.

Il controller T6963

Il chip T6963, impiegato su molti modelli di lcd, e’ costruito dalla Toshiba ed e’ molto semplice e divertente da utilizzare. Puo’ essere configurato per controllare vari formati di LCD (tipicamente, in commercio, lo troviamo in moduli  con matrici di 128x64 pixel, 128x128 o 240x64), puo’ indirizzare un massimo di 64Kbyte di memoria RAM esterna , e’ dotato di ROM interna per la generazione di una parte dei caratteri del set ascii (C.G. ROM) con 4 diverse “fonts” selezionabili; puo’, inoltre, essere usato in modo testo, in modo grafico e permette di  “miscelare” con tre diverse modalita’ (AND, OR, EXOR) la pagina di memoria grafica visualizzata con quella di testo.

figura1

<Figura 1> il display 240x64 pixel con T6963

L’interfaccia

Qualche mese fa sono entrato in possesso di uno di questi moduli (MGLS24064) dotato di LCD a matrice di  240x64 pixel ed equipaggiato, appunto, con il controller T6963 della Toshiba, cosi’ ho cominciato a fare qualche prova sfruttando il kit di svilluppo del’AT90S8515 costruito tempo addietro.

La prima osservazione e’ che, per connettersi con questo modulo, ed in generale con altri analoghi, e’ necessario impegnare ben 13 linee di I/O ( 8 pin di ingresso/uscita dati e comandi e 5 pin di controllo) che per il micro 8515 significa usare quasi due porte complete, cioe’ la meta’ di linee di I/O che sono disponibili in totale. Di qui’ l’idea di realizzare un semplice circuito di interfaccia che “serializzando” il flusso dati consenta il risparmio di 6 linee di I/O, permettendo cosi’ di destinare una sola porta del microcontrollore a tale scopo. Questa  scheda si adatta bene al kit di sviluppo che ho realizzato per l’8515, perche’ consente di riutilizzare il connettore presente, che inizialmente era stato pensato per connettere un display di tipo alfanumerico.

Un aspetto negativo di tale interfaccia e’ il prolungamento del tempo di invio e ricezione dei dati che orientativamente verra’ incrementato di un fattore otto (pari al numero di bit da trasferire in seriale). Considerando pero’ che il microcontrollore AT90S8515, con clock a 8MHz, esegue una istruzione in 125ns ne consegue che un trasferimento di un byte di dati viene effettuato in un tempo, comunque, relativamente breve (1-1.5 microsecondi).

E’ possibile, tuttavia, non costruire la scheda proposta e pilotare il display grafico con due porte di I/O del microcontrollore adottando, in ogni caso, il driver fornito con questo articolo (con qualche modifica al codice).

figura2

<Figura 2> il prototipo in funzione connesso al kit dell’8515

Schema elettrico

schematic

Lo schematico e’ composto, essenzialmente, di un convertitore seriale/parallelo per la comunicazione dal nostro microcontrollore al modulo lcd, di un convertitore parallelo/seriale per la trasmissione opposta e di un invertitore DC/DC che serve a fornire la tensione negativa di “bias” necessaria al display.

L’adattatore seriale/parallelo e’ realizzato con lo “shift register” 74HC164 (U1), la cui funzione e’ di trasferire i bytes di dati, provenienti dal micro in formato seriale, dall’ingresso (A e B: pin1 e 2) alle 8 uscite parallele (da Q0 a Q8: pin3,4,5,6,10,11,12,13). Ogni ciclo di clock i bit seriali verranno via via presentati dal micro (uscita PA3) all’ingresso dello “shift register” HC164 e successivamente “shiftati” attraverso i “flip-flop” interni fino a raggiungere l’uscita corrispondente all’ordine di invio. Quindi nel tempo di otto “colpi” di clock, cadenzati dal microcontrollore (uscita PA2 connessa all’ingresso di clock, pin 8 dell’HC164), avremo il byte disponibile sugli otto piedini d’uscita (vedi anche diagramma di figura 5).

In uscita e’ connesso un “buffer tristate” tipo 74HC244 (U3) che ha l’unico scopo di isolare l’HC164 dalle linee di I/O del display; infatti quando e’ chiamato a trasmettere un dato potrebbe entrare in conflitto con i livelli logici rimasti presenti nelle uscite dell’HC164, falsandone la lettura da parte del micro.

Il “buffer” e’ comandato dal pin PA1 del micro che lo abilitera’ in trasmissione presentando gli otto bit di dati ai corrispondenti ingressi del display.

In senso opposto troviamo un altro “shift register” il 74HC165 (U2) che in maniera complementare al primo sara’ “caricato” in modo parallelo (ingressi da D0 a D7: pin 11,12,13,14,3,4,5,6) dalle uscite del display e di seguito trasferira’ i bit d’ingresso uno alla volta sull’uscita seriale (Q: pin 9) che, naturalmente verra’ letta dal microprocessore, ingresso PA5 (vedi anche diagramma di figura 6). Preciso che il clock, adoperato da questo componente, e’ condiviso con l’HC164  dato che le operazioni di lettura e scrittura da e verso il modulo del display sono per forza effettuabili in maniera separata.

L’ultimo blocco del circuito e’ costituito da un convertitore DC/DC per trasformare la tensione di alimentazione (+5V) che forniremo al piastrino (dal connettore d’ingresso) nel valore di circa -14V negativo rispetto alla massa del circuito. A tale proposito, c’e’ da premettere che non tutti i display LCD in commercio necessitano di un’alimentazione negativa (oltre alla classica +5V), perche’ magari gia’ includono nel modulo un generatore interno per fornire tale tensione; ovviamente in questo caso possiamo omettere di montare questa parte di circuito.

Ho realizzato questo convertitore non impiegando, volutamente, dispositivi integrati gia’ pronti a quest’uso specifico. Il motivo e’ perche’, in primo luogo, di dc/dc converter in chip utilizzabili per questa applicazione ve sono molti (vedi cataloghi Maxim, Linear etc...) e quindi proponendo un componente specifico questo poteva risultare di difficile reperibilita’ per qualcuno, ed inoltre il circuito applicativo per questi convertitori dc/dc integrati e’, in genere, estremamente semplice (necessitano di pochissimi componenti esterni) e documentato bene sul relativo datasheet.

Al contrario vorrei proporvi un dc/dc converter realizzabile con componenti di facile reperibilita’.

Troviamo, per cui, l’intramontabile timer 555 connesso in configurazione astabile per realizzare un oscillatore  la cui frequenza e’ determinata da C5, R3 ed R4 (che con i valori indicati dovrebbe risultare intorno ai 15KHz). Il 555 pilota, sfruttando occasionalmente anche l’uscita 7 (discharge), un driver “push-pull” formato dai due transistors Q1 e Q2 (sostituibili con equivalenti PNP ed NPN) che garantisce un segnale ad onda quadra che puo’ fornire una corrente adeguata allo stadio che segue. Il segnale cosi’ ottenuto viene invertito, triplicato, con un classico moltiplicatore di tensione di “Cockcroft-Walton” realizzato con i diodi D1-D6 e le capacita’ C8-C13 e raddrizzato in modo da ottenere una tensione di circa –14 V. Sullo schema ho specificato che i diodi da utilizzare sono Schottky perche’ questi ultimi presentano una tensione di soglia caratteristica (e quindi una caduta di tensione) piu’ bassa dei comuni diodi. Utilizzando, tuttavia, i piu’ diffusi 1N4148 si riuscira’ ad ottenere una tensione di circa –12V che potrebbe gia’ essere sufficiente per il display che avete deciso di utilizzare (controllate il datasheet). La tensione convertita sara’ infine connessa al display tramite il trimmer resistivo R7 che ci permettera’ di regolare il contrasto dell’LCD.

figura3

<Figura 3> la schedina in primo piano montata su basetta preforata

Montaggio

Il circuito, piuttosto semplice, non richiede, a mio parere, la realizzazione di un circuito stampato apposito. Di conseguenza ho optato per il montaggio su un pezzetto di basetta millefori eseguendo le connessioni con un sottile filo rigido e isolato.

Potrete posizionare i componenti a vostro piacimento avendo sempre l’accortezza di saldare la capacita’ di bypass vicino ai pin d’alimentazione di ogni circuito integrato.

Per la connessione dei display ho preferito montare sulla millefori un connettore a 20 pin usando poi un cavo “flat” verso l’lcd. La “strip” di contatti J1 e J2 andra’, invece, assemblata da un lato del piastrino in modo da far coincidere i segnali con quelli dello starter kit; avremo cosi’ la possibilita’ di inserire il piastrino tipo “piggy-back” sul circuito stampato del kit (vedi figura 4).

figura4

<Figura 4> l’interfaccia collocata sul kit AVR8515

Il firmware di controllo del modulo lcd

Per prima cosa analizzeremo come avviene lo scambio di byte, tramite l’interfaccia che abbiamo realizzato,  dal micro verso il display e viceversa ed in seguito esamineremo il flusso di comandi e dati necessarie all’inizializzazione ed al pilotaggio del modulo lcd.

La figura 5 ci mostra il diagramma temporale della trasmissione (dal micro verso il display) di un byte di dati. La prima operazione eseguita e’ il caricamento dello shift register dell’interfaccia con il dato da trasmettere, compiuta con 8 cicli di clock. A questo punto il micro mettera’ a livello “1” o “0” il segnale di I/O PA3 a seconda che il byte che ci interessa trasferire sia un dato o un comando (segnale Command/Data del display) , quindi presentera’ il byte utile all’ingresso dell’lcd, abilitando il buffer HC244 con PA1, ed infine inviera’ il segnale di scrittura ( lcd WR) con PA4.

La figura 6 mostra l’operazione inversa, cioe’ la lettura di un byte (dal display verso il micro). In questa ipotesi, il micro mettera’ a livello “1” o “0” il segnale di I/O PA3 (pin C/D del display) a seconda che il byte che ci interessa leggere sia un dato o lo “status byte” , l’operazione successiva sara’ l’abilitazione del segnale di lettura (lcd RD) che ha il duplice scopo di abilitare il display in trasmissione e consentire il caricamento parallelo dello “shift register” HC165. Per ultimo il byte pronto all’ingresso dell’HC165 sara’ letto dal micro serialmente bit per bit (da PA5) con 8 cicli di clock.

figura5

<Figura 5> Diagramma temporale della scrittura di un byte dal micro all’lcd

figura6

<Figura 6> Diagramma temporale della lettura di un byte dall’lcd al micro

figura7

<Figura 7>Struttura della RAM e della matrice LCD in un modulo con controller T6963

La figura 7 mostra l’organizzazione interna della RAM riferita ad un modulo con matrice di pixel 240x64.

Dal disegno possiamo notare due aree di memoria definite (nel modo che vedremo in seguito) per la pagina grafica e per la pagina di testo. In queste due aree scriveremo le informazioni da visualizzare ed il controller si prendera’ cura di trasferirle alla matrice lcd. Si potra’, quindi, utilizzare la modalita’ solo testo, solo grafica o le due pagine potranno essere “mixate” con tre differenti possibilità.

Istruzioni e dati

I diagrammi di flusso di figura 8 tratti dal datasheet del T6963 espongono la procedura generica per la trasmissione di un comando. Il “Flowchart” (A) mostra la trasmissione di un comando con un parametro, mentre nel caso (B) i parametri da inviare sono due.

Seguendo il piu’ generico caso (B) troviamo nell’ordine:

1) l’operazione di lettura dello “Status check” byte con particolare riferimento ai bit STA0 e STA1. Questi due bit ci indicano (se posizionati a livello logico “1”) la disponibilita’ del controllore T6963 ad accettare comandi (se STA0=1) e dati (se STA1=1). Questo passo ( che va ripetuto prima di ogni invio di byte) e’ fondamentale per capire se il controllore e’ pronto per accettare la nostra trasmissione ovvero se e’ libero dall’effettuare operazioni interne;

2) la scrittura del primo parametro;

3) di nuovo il controllo dello “Status byte”;

4) la scrittura del secondo parametro;

5) nuovamente il controllo dello “Status byte”;

6) infine l’invio del byte che definisce il comando da eseguire con i parametri precedentemente forniti.

Come esempio pratico, ipotizziamo di comunicare al modulo di posizionare il suo puntatore all’indirizzo di memoria 03E8 esadecimale, che equivale ad una locazione fisicamente collocata piu’ o meno al centro della matrice del nostro lcd. Supponiamo di effettuare questo posizionamento per poi voler “accendere” dei pixel in quel punto. La sequenza sara’ quindi:

1) STATUS BYTE CHECK dei bit STA0, STA1;

2) scrittura del byte meno significativo (LSB) dell’indirizzo (E8 esadecimale nel nostro esempio);

3) STATUS BYTE CHECK dei bit STA0, STA1;

4) scrittura del byte piu’ significativo (MSB) dell’indirizzo (03 esadecimale);

5) STATUS BYTE CHECK dei bit STA0, STA1;

6) invio del byte di comando 24 esadecimale che corrisponde al “set address pointer” (vedi figura 9: “command definitions”).

A questo punto il puntatore di indirizzo e’ fissato sulla locazione che ci interessa e non ci resta che ripetere la sequenza di trasmissione per, ad esempio, “accendere” dei pixel (vedi comando “bit set” nel datasheet T6963).

Il driver

Come anticipato ad inizio articolo, ho scritto un “driver” per il controllo delle funzioni principali del lcd utilizzando il microcontrollore AT90S8515.

Analizzeremo qualche funzione partendo dalla procedura d’inizializzazione, da effettuare subito dopo aver alimentato il modulo, operazione espletata dalla funzione “init_graph_display()”.

In particolare le azioni eseguite sono le seguenti:

- configurazione della porta di I/O (PORT A) del micro dove andra’ connessa l’interfaccia costruita e l’lcd;

- reset del modulo lcd per 5 millisecondi comandato da PA0;

- invio del comando “set graphic home address” che permette di definire la corrispondenza della “home” del display, cioe’ la locazione in alto a sinistra, con il primo indirizzo della area di RAM. Per comodita’ nel driver questo e’ definito a 0000 cioe’ il primo punto in altro a sinistra sara’ il bit 7 dell’indirizzo 0000, il secondo punto sara’ il bit 6 dell’indirizzo 0000 e cosi’ via ... il nono punto sara’ il bit 7 dell’indirizzo 0001 etc... E’ facilmente intuibile che muovendo la “finestra” di memoria del display all’interno della RAM disponibile si puo’ ottenere uno “scrolling” dei dati o cambi completi di pagina (vedi anche figura 7).

- invio del comando “set graphic area” che serve a definire l’ampiezza (in byte in senso orizzontale) della matrice lcd e quindi dipende dal display posseduto. Nel mio caso ho 240 pixel orizzontali, cioe’ 30 byte (8pixel=1byte) quindi e’ definito a 30 (001E esadecimale).

Nulla vieta di definire l’area maggiore di quella che effettivamente e’ (ad esempio per semplificare il calcolo dell’indirizzo d’inizio riga), definirla piu’ piccola, invece, puo’ portare a malfunzionamenti.

 - invio del comando “set text home address”. E’ l’equivalente di “set graphic home address” valido pero’ per la pagina in modo testo. Nel driver questo indirizzo e’ fissato a 0780 esadecimale cioe’ esattamente alla fine della pagina di memoria grafica (nel mio display grande 1920 bytes = 30byte x 64 righe).

- invio del comando “set text area”. Analogamente per l’area grafica bisogna definire l’ampiezza dell’area di testo che nel mio caso equivale a 30 colonne. Opzionalmente qualche modello di display da’ la possibilita’ di selezionare (tramite un pin hardware) due o piu’ tipi di “fonts” di carattere; in tal caso l’ampiezza puo’ variare dipendentemente dalla “font” utilizzata.

- invio del comando “mode set”. Definisce il modo in cui vogliamo “miscelare” la pagina grafica con quella di testo che, come spiegato in precedenza, possono essere visualizzate contemporaneamente. In tale ipotesi potremo scegliere tra tre modalita’ OR, AND, EXOR che evidentemente realizzano le tre operazioni logiche tra i bit della pagina testo e grafica.

- invio del comando “display mode”. specifica la visualizzazione o meno della pagina grafica, di testo o entrambe (nella modalita’ vista nell’istruzione che precede) e la possibilita’ di mostrare e far lampeggiare il cursore (le cui dimensioni sono eventualmente specificate con un altro comando).

A questo punto l’inizializzazione e’ terminata ed il display e’ pronto ad accettare le nostre informazioni da visualizzare.

Tra le funzioni utili, incluse nel codice del “driver”, posso citare “gput_number()” o “gput_string()” che permettono l’invio alla pagina testo rispettivamente un numero 0-255 (8 bit) o una stringa di caratteri alfanumerici; mentre “gpixel()” permette il controllo pixel per pixel della pagina grafica.

Oltre al “driver” forniro’ un programma dimostrativo che fa’ uso di queste funzioni. 

Conclusione

Per concludere vorrei segnalarvi un programma “freeware” disponibile in rete che converte disegni o immagini dal formato bitmap (.bmp) al formato esadecimale per l’invio diretto sul display. L’applicazione e’ “Fastlcd”  scaricabile nella sezione “download” del sito http://www.fastavr.com/ .

Elenco componenti

Sigla

Valore

R1,R4,R5,R6

Resistenza 1K 1/4W

R3

Resistenza 47K 1/4W

R7

Trimmer Resistivo 20K

C1-C4,C6,C7

Condensatore poliestere 100nF 63V

C5

Condensatore poliestere 1nF 63V

C8-C13

Condensatore elettrolitico 1µF 25V

D1-D6

Diodo Schottky 1N5818 o simili (in alternativa 1N4148)

J1, J2

“Strip" di terminali

P1

Connettore 20 pin (o 2 strip da 10 pin)

U1

Circuito Integrato 74HC164

U1-holder

zoccolo portaintegrato da 14 pin

U2

Circuito Integrato 74HC165

U2-holder

zoccolo portaintegrato da 16 pin

U3

Circuito Integrato 74HC244

U3-holder

zoccolo portaintegrato da 20 pin

U4

Circuito Integrato LM555

U4-holder

zoccolo portaintegrato da 8 pin