Pilote affichage lcd 2x16 en mode parallèle 8 bits

Contenu du snippet

Handicapé par la non connaissance de l'assembleur pour les PICs de chez Microchip, j'ai développé les drivers pour afficheur LCD 2x16 (compatible HITACHI). Après bien de vicissitudes avec les timings, voici le source d'un pilote pour "driver" en mode parallèle 8 bits en C.
Je traville sous MBLAB IDE avec CCS C Compiler.
Ce petit source doit être copié dans votre source. En effet, en passant par une directive de compilation "#iclude <LCD_8.c>, le compilateur a des difficultés de digestion et demande des déclarations de devices qui existent déjà dans le "main" !
Vous disposerez ainsi de toutes les commandes basiques et surtout de la séquence d'initialisation de l'afficheur.
Si j'ai fait des bêtises, pardonnez et dites le : je débute en C et sur les microcontroleurs!!!
Oui, les commentaires sont parfois en anglais, parfois en francais !

Merci à tout ceux qui ont eu la bonne idée de donner des informations sur le Net !!

Les delays sont valables pour une horloge à 20MHz sur le PIC. Avec un quartz de 4MHz, ne vous attendez pas à une durée de cycle de 50ns !!!
La durée basique est de T (en secondes) = 1 / F(en Hertz).

Source / Exemple :


//
//
//	Routines LCD en mode donnees 8 bits
//
//
//	Necessite #include <math.h>
//
//	
//	PORTB bits 0-7 : lcd_b.data      LCD pins 7-14	(Data)
//
//	PORTD bit 0    : lcd_d.enable    LCD pin 6	(LCD Enable)
//	PORTD bit 1    : lcd_d.rw        LCD pin 5   	(LCD Read Write)
//	PORTD bit 2    : lcd_d.rs        LCD pin 4   	(LCD Register Select)
//
//	Masse          :                 LCD pin 1
//	+5V            :                 LCD pin 2
//	Contraste      :                 LCD pin 3					
//
// Write operations :	RS = 0 except Write Data t0 CG or DD RAM - RW = 0
// ****************
//		x = don't care
// Clear Display				: 00000001 (1.64ms)
//
// Home Cursor					: 0000001x (40µs à 1.64ms) 
//
// Entry Mode Set				: 000001is (40µs) [00000110]
//		i = 0 decrement; i = 1 increment DD RAM address by 1 after each wrire or read
//		s = 0 no display scroll, s = 1 displays scroll in the direction specified by i
//								  
// On/Off Control				: 00001dcb (40µs) [00001000 puis 00001110]
//		d = 0 display Off, d = 1 display on
//		c = 0 cursor off, c = 1 cursor on
//		b = 0 no blink character, b = 1 blink character at cursor position
//
// Cursor Shift					: 0001srxx (40µs) [00010100]
//		s = 0 move cursor, s = 1 scroll display
//		r = 0 to left, r = 1 to right
//
// Function Set					: 001dnfxx (40µs) [00111000]
//		d = 0 4 bits interface, d = 1 8 bits interface
//		n = 0 For 2 lines display : 1 line, n = 1 2 lines - else n = 0 1/8 or 1/11 duty, n = 1 1/16 duty
//		f = 0 5x8 dots, f = 1 5x11 dots
//
// Character Address RAM Set	: 01aaaaaa (40µs)
//		aaaaaa = 6 bits CG RAM address to point
//
// Display RAM Address Set		: 1aaaaaaa (40µs)
//		aaaaaaa = 7 bits DD RAM address to point
//
// Write Data t0 CG or DD RAM	dddddddd with RS = 1 
//		(40µs for display write DD RAM, 120µs for character generator ram write CG RAM)
//		dddddddd = 8 bits character code
//
// Timing : 
//		valid data b0 to b7
//		delay 25ns
//		RS
//		delay 150ns
//		RW
//		delay 150ns
//		Enable = 1
//		delay 2µs
//		Enable = 0
//		Delay 150µs
//
//
// Read operations :	RS = specified - RW = 1
// ***************
//
// Read Busy Flag				: baaaaaaa RS = 0 (1 cycle)
//		Read status of busy flag and the value of the RAM address currently being pointed at.
//		b = 0 OK, b = 1 Busy
//		aaaaaaa = 7 bits current DD/CG RAM address counter
//
// Read Data From CG or DD RAM	: zzzzzzzz RS = 1 (40µs for DD RAM read, 120µs for CG RAM read)
//		Data is read from current address position and the RAM address is automatically incremented/decremented
//      by 1 as determined by the "Entry Mode Set" command. The cursor is not shifted  to.
//		zzzzzzzz 8 bits address RAM, a 8 bits character code will be read back from LCD RAM.
//
//
// RAM Address :
//		DD RAM :128 - 255
//		CG RAM : 64 - 127
// LCD Address :
//		line 1 : 00h to 0Fh
//		line 2 : 40h to 4Fh
//
// Initialisation 8 bits :
// *********************
//		RS	RW	Data		Delay
//							15ms (after Vdd rises to 5V)
//		0	0	0x30	
//							5ms
//		0	0	0x30
//							200µs
//		0	0	0x30		
//							200µs
//		0	0	Function Set : 0x38
//							200µs
//		0	0	Display OFF	0x08	Now Busy Flag may be tested
//							Busy Flag
//		0	0	Clear Screen 0x01
//							Busy Flag
//		0	0	Entry Mode Set 0x06
//							Busy Flag
//

struct lcd_b_pin_map 
	{
	int     data : 8;	// bits 0 a 7
	}
	lcd_data;

struct lcd_d_pin_map 
	{
	BOOLEAN enable;		// bit 0
	BOOLEAN rs;			// bit 1
	BOOLEAN rw;			// bit 2                                                           
	BOOLEAN unused : 5;	// bit 3 à 7
	}
	lcd_cmd;

#byte lcd_data = 6           // on to port B (at address 6)
#byte lcd_cmd = 8           // on to port D (at address 8)

#define set_tris_lcd_data(x) set_tris_b(x)
#define set_tris_lcd_cmd(x) set_tris_d(x)

#define Port_In		0xFF					// All bits to high level
#define Port_Out	0x00					// All bits to low level
#define First		0x30					// Premier mot sequence initialisation LCD
#define FunctionSet	0x38					// 8 bits, 2 lignes, 5x7
#define DisplayOff	0x08					// Display Off, Cursor Off
#define CursorShift	0x14					// Shift Cursor a droite
#define DisplayOn	0x0C					// Display On, Cursor Off
#define ClearScreen	0x01					// Cursor 0,0 et clear afficheur
#define Home		0x02					// Curseur 0,0
#define EntryMode	0x06					// Increment RAM address & no shift display

#define lcd_strobe	delay_cycles(2);lcd.enable = 1;delay_cycles(2);lcd.enable=0;delay_cycles(2)

//
//
/**********************************/
/* Definition des utilitaires LCD */
/**********************************/
//
//

//
// Lecture d'un octet
//
char lcd_read()
	{
	char Valeur;
	
	set_tris_lcd(Port_In);  	// Data en entree
	delay_cycles(1);		// delay 50ns

	// Passage en lecture
	lcd.rs = 0;
	delay_cycles(1);		// delay 50ns
	lcd.rw = 1;

	lcd_strobe;
	Valeur = lcd.data;
	delay_cycles(5);		// delay 250ns

	set_tris_lcd(Port_Out);  	// Data en sortie
	delay_cycles(1);

	return (Valeur);
	}

//
//      Test le bit BF jusqu'a ce que le LCD soit ok
//
void lcd_busy()
	{
	int tem;
	
	set_tris_lcd(Port_In); 	// Port data en entree

	do
		{
		tem = lcd_read() && 0x80;
		}
	while(tem != 0);		// Boucle tant que BF=1

	set_tris_lcd(Port_Out); // Port data en sortie
	}        		  	 

//
// Ecriture d'un octet dans le LCD
//
void lcd_write_cmd(char c)
	{
	// Port data en sortie
	set_tris_lcd(Port_Out);
	delay_cycles(1);

	// Passage en ecriture cmd
	lcd.rs   = 0;					// mode commande
	delay_cycles(1);				// delay 50ns
	lcd.rw   = 0;					// mode ecriture
	delay_cycles(1);				// delay 50ns
	
	// Ecriture
	lcd.data = c;					
	delay_cycles(30);				// delay 1.5µs
	lcd_strobe;					// echantillonage MSB
	delay_cycles(30);				// delay 1.5µs
	}

//
// Ecriture d'un octet dans le LCD
//
void lcd_write_char(char c)
	{
	// Port data en sortie
	set_tris_lcd(Port_Out);
	delay_cycles(2);		// delay 100ns

	// Test LCD
	lcd_busy();

	// Passage en ecriture caractere
	lcd.rs = 1;
	delay_cycles(2);				// delay 100ns
	lcd.rw = 0;
	delay_cycles(10);				// delay 500ns

	// Traitement MSB
	lcd.data = c;
	delay_cycles(30);				// delay 1.5µs
	lcd_strobe;
	delay_cycles(30);				// delay 1.5µs
	}

//
// Ecriture d'une chaine de caracteres 
//
void lcd_writestring(char *s)
	{
	while(*s)
		{
		lcd_write_char(*s++);
		}
	}

//
// Positionne le curseur ligne, position
// la premiere ligne est la ligne 0
//
void lcd_pos(char ligne, char pos)
	{
	lcd_write_cmd(((ligne * 0x40) + pos) + 0x80);	
	}

//
// 	Efface l'ecran et curseur home 
//
void lcd_clear() //  exe 1.64ms
	{
	lcd_write_cmd(ClearScreen);
	}
//    
// Curseur Home    
//
void lcd_home() // exe 1.64ms
	{
	lcd_write_cmd(Home);
	}

//
// Fait clignoter le caractere affiche
//

void lcd_clign_on() // 
	{	
	lcd_write_cmd(0x0D);
	}

//
// Arrete le clignotement
//
void lcd_clign_off()
	{
	lcd_write_cmd(0x0C);
	}
//
// Shift à droite du curseur
//
void lcd_CurShift()
	{
	lcd_write_cmd(CursorShift);
	}

//
// decalage a gauche
//
void lcd_decal_gauche()
	{
	lcd_write_cmd(0x4);
	}
//
// decalage a droite
//
void lcd_decal_droite()
	{
	lcd_write_cmd(0x6);
	}

void lcd_on()
	{
	lcd_write_cmd(0x0E);
	}

void lcd_off()
	{
	lcd_write_cmd(0x08);
	}

//
// initialise l'afficheur LCD en mode 8 bits
//
void lcd_init()
	{
	set_tris_lcd(Port_Out); 	// Port data en sortie
	Delay_ms(25);

	lcd_write_cmd(First); // 1
	Delay_ms(5);

	lcd_write_cmd(First); // 2
	Delay_us(200);

	lcd_write_cmd(First); // 3
	Delay_us(200);

	lcd_write_cmd(FunctionSet);	// Function Set : 8 bits, 2 lignes, 5*8 (40µs)
	Delay_us(50);

	lcd_write_cmd(DisplayOff); 	// On/Off Control : Affichage & curseur  off (40µs)
	Delay_us(50);

	lcd_write_cmd(DisplayOn); 	// On/Off Control : Affichage & curseur  on (40µs)
	Delay_us(50);

	lcd_write_cmd(ClearScreen);	// Clear Display : clear et home (1.64ms)
	Delay_ms(2);

	lcd_write_cmd(EntryMode);	// Entry Mode Set : pas de decalage digits LCD (40µs)
	Delay_us(50);
	}

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.