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);
}
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.