Programació en C del PIC 16F690 amb PICkit 2

.
Referència Trucs Perifèrics  Recursos CITCEA
Tutorial Exemples Projectes   Inici

Pantalla LCD amb connexió paral·lel de quatre bits

Anem a afegir una pantalla LCD al nostre microcontrolador. Les pantalles LCD porten normalment un circuit integrat que les controla (un altre microcontrolador) que permet que nosaltres li enviem la configuració i els caràcters a mostrar. Si no hi hagués aquest circuit integrat, nosaltres hauríem de controlar tots els punts (píxels) de la pantalla i ens faltarien ports.

Els controladors de pantalla es poden comunicar amb el microcontrolador en sèrie o en paral·lel.

La comunicació paral·lel requereix un conjunt de quatre o vuit bits de dades i entre dos i quatre bits de control; per tant haurem de reservar entre sis i dotze potes dels ports del microcontrolador. Té l'avantatge que els bits s'envien tots d'un cop i, per tant, la programació és més senzilla.

La comunicació sèrie es fa enviant els bits un darrere l'altre i, per tant, cal gestionar el canal de comunicació. Amb comunicació sèrie la programació és més complexa però es necessiten molt poques potes (normalment dues o tres) per a la comunicació.

Aquest apartat es basa en les pantalles paral·lel de 16 per 2 i 20 per 4 de l'empresa Xiamen Ocular. Jo les he comprat al web de la casa Sparkfun.

En el cas de les pantalles, més important que el full de característiques de la pantalla és el full de característiques del controlador. En aquest cas el controlador és el S6A0069. Podeu trobar la taula de caràcters que porta implementats en aquest full de característiques.

Per connectar la pantalla amb el microcontrolador, cal decidir quins ports fem servir. En aquest cas les connexions de dades les hem posat al port C i les de control al port B. Com no hem previst llegir del controlador de la pantalla, la pota R/W la deixem sempre al negatiu (massa, GND); és a dir, sempre com escriptura. Atès que treballem amb quatre bits de dades, les potes DB0 a DB3 tampoc les fem servir i, per evitar interferències, les connectem a massa. La taula de connexions queda així:

Pantalla Microcontrolador                                         Pantalla Microcontrolador
Pota Nom Nom Pota Pota Nom Nom Pota
1 VSS (GND) VSS (GND) 20 9 DB2 VSS (GND) 20
2 VDD (5 V) VDD (5 V) 1 10 DB3 VSS (GND) 20
3 V0 (contrast) Potenciòmetre (19) 11 DB4 RC4 6
4 RS RB5 12 12 DB5 RC5 5
5 R/W VSS (GND) 20 13 DB6 RC6 8
6 E RB7 10 14 DB7 RC7 9
7 DB0 VSS (GND) 20 15 LED+
8 DB1 VSS (GND) 20 16 LED-

Es recomana connectar l'entrada de contrast de la pantalla a un potenciòmetre que permeti variar la tensió aplicada per trobar el contrast més adequat. Per a fer proves, podem connectar-lo a la pota 19 del microcontrolador on hi tenim el potenciòmetre de la placa que ens donarà la tensió variable que necessitem. Girant el potenciòmetre de la placa trobarem el contrast més adequat.

Les darreres potes (LED+ i LED-) serveixen per alimentar un LED que ilumina la pantalla. En la majoria d'aplicacions no és necessari connectar-lo ja que la pantalla queda iluminada per la llum ambient.

En el mode en el que treballarem, no comprovem si la pantalla està preparada per rebre les nostres comandes. Després d'enviar-li algunes comandes que requereixen un cert temps de treball per part del controlador de la pantalla convé esperar una mica (per exemple, 100 ms) abans d'enviar-li una nova comanda.

En teoria, només cal inicialitzar i configurar la pantalla un cop, a l'inici del programa. En alguns casos, si l'alimentació no és estable, ens podem trobar que surtin caràcters anòmals a la pantalla. En aquests casos, pot ser convenient repetir la inicialització i la configuració cada cop que escrivim a la pantalla.

Inicialització de la pantalla

La inicialització de la pantalla ha de seguir una pauta que estableix el fabricant del controlador. En el cas del mode de funcionament de quatre bits, aquesta pauta s'ha de seguir estrictament ja que sinó la configuració quedarà a vuit bits.

D'entrada cal esperar un mínim de més de 0,1 s a que el controlador de la pantalla hagi inicialitzat. Si no ho fem, el que enviem probablement es perdi. Segons la documentació del fabricant, aquest temps pot ser molt més petit però si alimentem el microcontrolador i la pantalla amb el gravador (PICkit) cal donar més temps. Tot seguit hem d'enviar el nibble 0010 seguit de la configuració bàsica (en dos nibbles).

void IniPant(void) {
	_delay(250000);	    			// Retard (250 ms)
	EnviaI(0b00100000);			// Function set - Configuració inicial  0010 al nibble de l'esquerra
	EnviaC(0b00101000);			// Configuració 2 línea, 5x8 píxels
}

Es recomana esperar un temps (per exemple, 100 ms) abans d'enviar una nova comanda a la pantalla per donar temps a que es realitzi la petició.

Configuració de la pantalla

La configuració de la pantalla pot ser de moltes maneres diferents. A continuació en fem servir una però els bits que estan en color podrien ser diferents si preferim una altra configuració.

void ConfPant(void) {
	EnviaC(0b00001111);			// Display ON/OFF control - Activa la pantalla amb cursor intermitent
	EnviaC(0b00000001);			// Clear display - Buida la pantalla i inicialitza
	_delay(3900);	    			// Retard (3,9 ms)
	EnviaC(0b00000110);			// Entry mode - Buida la pantalla, sentit dreta i despl. automàtic
}

Es recomana esperar un temps (per exemple, 100 ms) abans d'enviar una nova comanda a la pantalla per donar temps a que es realitzi la petició.

Esborrat de la pantalla

Podem esborrar la pantalla amb la següent instrucció:

	EnviaC(0b00000001);			// Clear display - Buida la pantalla i inicialitza

Es recomana esperar un temps (per exemple, 100 ms) abans d'enviar una nova comanda a la pantalla per donar temps a que es realitzi la petició.

Retorn a l'inici

Podem tornar el cursor a l'inici (sense esborrar la pantalla) amb la següent instrucció:

	EnviaC(0b00000010);			// Return Home - Posa el cursor a 00h

Es recomana esperar un temps (per exemple, 100 ms) abans d'enviar una nova comanda a la pantalla per donar temps a que es realitzi la petició.

Caràcters i posició a la pantalla

El controlador de la pantalla té una memòria per als caràcters que es visualitzen anomenada DDRAM. Cada posició de la pantalla correspon a un byte a la DDRAM però no tots els bytes de la DDRAM es visualitzen.

La primera línia de la pantalla comença a l'adreça 00h. En pantalles de dues línies, la segona línia comença a la posició 64 (40h). Si la pantalla té més línies, la tercera començarà a continuació de la primera i la quarta a continuació de la segona. En una pantalla de 16 caràcters per línia es visualitzaran a la primera línia les posicions 00h a 0Fh i en una de 20 caràcters serà fins a la 13h.

La taula de caràcters és, en principi, la dels codis ASCII. Per tant per als caràcters normals podem treballar directament en ASCII. Algunes de les adreces que en els codis ASCII no hi són (més de 7Fh) o algunes de les que corresponen a caràcters de control contenen símbols que el fabricant de la pantalla ha decidit posar-hi.

Les adreces de la DDRAM són de set bits (0 a 6). Per dir-li al controlador a quina adreça volem escriure cal enviar-li com a caràcter de control el valor de l'adreça però amb el bit 7 a 1. Així per demanar-li que es posi a la primera posició (adreça 00h, 00000000) li enviarem el caràcter de control 10000000. Un cop li hem dit la posició i hem escrit un caràcter, el següent es posarà al costat. Per tant només hem de canviar l'adreça quan la posició no sigui consecutiva. La següent funció coloca el cursor en la posició desitjada:

void Cursor(char Filera, char Columna) {
	char Posicio = 0;			// Variable per a calcular la posició
	if (Filera == 2) {
		Posicio = 64;			// La primera columna de la segona fila és 64;
	}
	if (Columna > 0 && Columna < 33) {	// Comprovem que sigui un valor raonable
		Posicio = Posicio + Columna;	// Sumem les adreces
		Posicio = Posicio - 1;		// Restem 1 perquè numera des de 0
	}
	Posicio = Posicio + 128;		// Posa el bit de posicionat a 1
	EnviaC(Posicio);			// Canvia el cursor de lloc
}

Enviament de caràcters

El següent conjunt de rutines serveix per enviar caràcters (lletres o de control) a la pantalla.

Tenim unes tres rutines. EnviaI serveix per enviar els caràcters d'inicialització que només són d'un nibble. La rutina EnviaC envia caràcters de control i EnviaL caràcters de text. La diferència entre aquestes dues és l'estat del pin RS.

La part més important d'aquestes dues rutines és idèntica. Primerament fa un retard que serveix per espaiar els caràcters i deixar temps per a que la pantalla els processi. Aquest temps és important ja que no llegim del controlador de la pantalla. Si llegíssim del controlador podríem saber si ja ha acabat o no i tenir esperes més curtes. Després configura els bits de control al port B (diferents segons si enviem caràcters de text o de control), passat un temps escriu el nibble de l'esquerra, després activa E durant uns microssegons i seguidament fa el mateix amb el nibble de la dreta.

void EnviaC(char Caracter) {
	_delay(800);	    			// Retard (0,8 ms)
	PORTB = 0b00000000;			// Desactiva E i RS
	_delay(3);	    			// Retard (3 us)
	PORTC = Caracter & 0xF0;		// Agafa els 4 bits més alts
	PORTB = 0b10000000;			// Activa E
	_delay(5);	    			// Retard (5 us)
	PORTB = 0b00000000;			// Desactiva E
	Caracter = Caracter << 4;
	PORTC = Caracter;			// Agafa els 4 bits més baixos
	PORTB = 0b10000000;			// Activa E
	_delay(5);	    			// Retard (5 us)
	PORTB = 0b00000000;			// Desactiva E
}
void EnviaL(char Caracter) {
	_delay(800);	    			// Retard (0,8 ms)
	PORTB = 0b00100000;			// Desactiva E i activa RS
	_delay(3);	    			// Retard (3 us)
	PORTC = Caracter & 0xF0;		// Agafa els 4 bits més alts
	PORTB = 0b10100000;			// Activa E
	_delay(5);	    			// Retard (5 us)
	PORTB = 0b00100000;			// Desactiva E
	Caracter = Caracter << 4;
	PORTC = Caracter;			// Agafa els 4 bits més baixos
	PORTB = 0b10100000;			// Activa E
	_delay(5);	    			// Retard (5 us)
	PORTB = 0b00100000;			// Desactiva E
}
void EnviaI(char Caracter) {
	_delay(800);	    			// Retard (0,8 ms)
	PORTB = 0b00000000;			// Desactiva E i RS
	_delay(3);	    			// Retard (3 us)
	PORTC = Caracter & 0xF0;		// Agafa els 4 bits més alts
	PORTB = 0b10000000;			// Activa E
	_delay(5);	    			// Retard (5 us)
	PORTB = 0b00000000;			// Desactiva E
}

Cal vigilar si fem servir altres bits dels ports B i C en altres aplicacions. Llavors hauríem de guardar els estats en una variable i fer servir les funcions and i or per a modificar només els bits que ens interessin.

Caràcters especials

La pantalla pot mostrar fins a 8 caràcters definits per l'usuari. Aquests caràcters són adreçables amb els codis ASCII 00h a 07h i els mateixos caràcters amb 08h fins 0Fh. Això vol dir que tan si posem 06h com 0Eh ens sortirà el mateix símbol.

Per crear els caràcters cal enviar una seqüencia de vuit bytes amb el patró corresponent. Els caràcters són de 5 per 8 píxels (punts) o sigui que hem d'enviar vuit valors en els que els tres primers bits (5, 6 i 7) són 0 i els altres cinc (0 a 5) són 1 si volem el punt activat i 0 si el volem desactivat. La següent figura mostra els 8 bytes que caldrien per crear la lletra Ω.

Caràcter especial omega

Els caràcters especials es guarden a la memòria CGRAM. El primer caràcter s'ha de colocar a les adreces 00h a 07h, el segon a les 08h a 0Fh i així successivament. El vuitè anirà de la 38h a la 3Fh.

El vuitè byte normalment ha d'estar a zero ja que allí és on ha d'aparèixer el subratllat del cursos. És recomanable que estigui a zero perquè en alguns programes hem detectat caràcters anòmals a la pantalla si no ho estaven.

Les adreces de la CGRAM són de sis bits (0 a 5). Per dir-li al controlador a quina adreça volem escriure cal enviar-li com a caràcter de control el valor de l'adreça però amb el bit 7 a 0 i el 6 a 1. Així per demanar-li que es posi a la primera posició (adreça 00h, 00000000) li enviarem el caràcter de control 01000000. Un cop li hem dit la posició i hem escrit un byte, el següent es posarà al costat. Per tant només hem de canviar l'adreça quan la posició no sigui consecutiva.

Per a crear caràcters especials podem fer servir la següent funció. Hem posat com a exemple la definició de la lletra omega.

char Omega[8] = {0b00000100, 0b00001010, 0b00010001, 0b00010001, 0b00001010, 0b00001010, 0b00011011, 0b00000000};
void DefCarac(char Numero, char Fileres[8]) {
	char Posicio = 0;			// Variable per a calcular la posició
	if (Numero  < 8) {			// Comprovem que sigui un valor raonable
		Posicio = Posicio * 8;		// Calculem l'adreça de memòria
	}
	Posicio = Posicio + 64;			// Posa el bit de caràcter especial a 1
	EnviaC(Posicio);			// Canvia el cursor de lloc
	for (int k = 0; k < 8; k++){
		EnviaL(Fileres[k]);		// Canvia el cursor de lloc
	}
}

Després d'enviar un caràcter especial, es recomana esperar un temps (per exemple, 100 ms) abans d'enviar una nova comanda a la pantalla per donar temps a que es realitzi la petició.

 

 

Licencia de Creative Commons
This obra by Oriol Boix is licensed under a Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported License.