Introduction
Lorsque on travaille avec un micro contrôleur on est vite limité en broches, comme un afficheur LCD en mode 4 bits utilise a lui seul 7 pin ( presque 1 port ). Et le routage n'est pas très simple.
C'est pourquoi j'ai voulu déporter ce port. A l'aide d'un simple PCF8574P qui lis ou écrit le port complet qui coute moins de 4€. Certains regarderont les versions commerciales et seront étonnés de voir une telle différence de prix, mais les versions commerciales ont un avantage: elles sont réalisées avec un micro contrôleur donc fonctionnent plus rapidement.
Fonctionnement du PCF8574P
Le PCF8574P est un composant I2C ( fonctionne sur le BUS I2C qui est un bus à 2 fils)
Petit cour sur l'I2C
Pour faire simple le PCF8574P se configure en entrée ou en sortie (pour tout le port). Donc il sera impossible de savoir l'état de l'afficheur, on le commanderas sans avoir de réponses, s'est pourquoi la version commerciale est plus rapide.
A savoir le BUS I2C comporte 3 fils ( un 4 éme si on souhaite ramener l'alimentation), La masse, SCL (horloge) et SDA (donnée). Le pic 16F876 possède un module I2C, mais si votre micro contrôleur n'en possède pas on peux utiliser 2 broches et le réaliser en programme ( je l'ai déjà fait avec un 68HC11 lors de mes études. ps : évitez ce micro contrôleur il y a 100 fois mieux pour moins cher )
Fonctionnement d'un afficheur LCD
Un afficheur LCD est composé de plusieurs parties:

* Un contrôleur ( driver LCD) qui communique avec l'extérieur et gère l'affichage. Les contrôleurs sont compatible entre eux ( se n'est pas le cas avec les afficheurs LCD graphique)
* Led de rétro éclairage ( pour activer le rétro éclairage ou non )
* Contraste: contraste de l'affichage ( valeur analogique compris entre 0 et 5 v , pour les LCD graphique , 0 et -5v)
Il existe plusieurs tailles d'écran, pour ma part , j'utilise un 16 x 2 (2 lignes de 16 caractères). Le module devrait être compatible avec les autres modèles.
Description des broches
| Numéro de broche du connecteur | Symbole | Type | Description |
| 1 |
GND |
alimentation |
masse (0V) |
| 2 |
Vdd |
alimentation |
+ 5 V (alimentation du contrôleur interne) |
| 3 |
V0 |
alimentation |
alimentation du panneau LCD
Ici a 0 v : contraste maximum |
| 4 |
RS (Register Select) |
entrée |
* RS = 1 : sélection du registre de données
* RS = 0 :
o en mode écriture : sélection du registre d'instruction
o en mode lecture : sélection du drapeau BUSY et du compteur d'adresse |
| 5 |
R/W (Read / Write) |
entrée |
* R/W = 1 : mode lecture
* R/W = 0 : mode écriture |
| 6 |
E (Enable) |
entrée |
Entrée de validation |
| 4 |
RS (Register Select) |
entrée |
* RS = 1 : sélection du registre de données
* RS = 0 :
o en mode écriture : sélection du registre d'instruction
o en mode lecture : sélection du drapeau BUSY et du compteur d'adresse |
| 5 |
R/W (Read / Write) |
entrée |
* R/W = 1 : mode lecture
* R/W = 0 : mode écriture |
| 6 |
E (Enable) |
entrée |
Entrée de validation |
| 7 |
DB0 (Data bit 0) |
entrée/sortie |
Bus de données (8 bits)
* DB0 : bit de poids faible (LSB)
* DB7 : bit de poids fort (MSB)
* En mode écriture : bus configuré en entrée
* En mode lecture : bus configuré en sortie
|
| 8 |
DB1 (Data bit 1) |
entrée/sortie |
| 9 |
DB2 (Data bit 2) |
entrée/sortie |
| 10 |
DB3 (Data bit 3) |
entrée/sortie |
| 11 |
DB4 (Data bit 4) |
entrée/sortie |
| 12 |
DB5 (Data bit 5) |
entrée/sortie |
| 13 |
DB6 (Data bit 6) |
entrée/sortie |
| 14 |
DB7 (Data bit 7) |
entrée/sortie |
| 15* |
A (Anode) |
alimentation |
alimentation du système de rétro éclairage |
| 16* |
K (Cathode) |
alimentation |
* seulement pour les modules LCD équipés de LED de rétro éclairage.
A noter: le contraste est toujours au maximum, si je réalise une V2, j'ajouterai le contraste.
La résistance pour le rétro éclairage n'est pas toujours obligatoire, je ne l'ai pas mis. Et je n'ai pas mis d'interrupteur, si je réalise une V2, un bornier permettras d'activer ou non le rétro éclairage pour économiser de la batterie...
Le jeu d'instruction
Le jeu d'instruction permet de communiquer avec l'afficheur en parlant le même langage. Tout n'est pas forcément utilisé/utile , mais si vous souhaitez faire clignoter quelque chose , je ne l'ai pas fait il vous faudra donc le faire en fonction de ce tableau...
| Instruction |
RS |
R/W |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
Description |
Durée (KS0070B à 270 kHz) |
| Display clear |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0
|
1 |
* Efface l'écran
* Place le curseur dans la position d'origine (1ère position à gauche, 1ère ligne : compteur d'adresse à 0x00)
|
1,53 ms |
| Return home |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1
|
X |
Place le curseur dans la position d'origine (1ère position à gauche, 1ère ligne : compteur d'adresse à 0x00)
|
1,53 ms |
| Entry mode set |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
I/D
|
S |
I/D = 1 : Déplacement du curseur d'une position à droite (Incrémentation du compteur d'adresse)
I/D = 0 : Déplacement du curseur d'une position à gauche (Décrémentation du compteur d'adresse)
S(Shift) = 1 : Décalage de l'affichage dans le sens de déplacement du curseur
S = 0 : L'affichage n'est pas décalé
|
39 µs |
| Display On/Off control |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
D |
C
|
B |
* D = 1 : affichage visible
* D = 0 : affichage invisible
* C = 1 : curseur visible
* C = 0 : curseur invisible
* B = 1 : curseur clignotant
* B = 0 : curseur fixe
|
39 µs |
| Cursor or display shift |
0 |
0 |
0 |
0 |
0 |
1 |
S/C |
R/L |
X
|
X |
* S/C = 1 : Décalage de l'affichage
* S/C = 0 : Déplacement du curseur
* R/L = 1 : Décalage à droite
* R/L = 0 : Décalage à gauche
N.B. Les données de la DDRAM* ne sont pas modifiées.
|
39 µs |
| Set Function |
0 |
0 |
0 |
0 |
1 |
DL |
N |
F |
X
|
X |
* DL = 1 : interface 8 bits
* DL = 0 : interface 4 bits
* N = 1 : 2 lignes d'affichage
* N = 0 : 1 ligne d'affichage
* F = 1 : matrice 5 x 11 points
* F = 0 : matrice 5 x 8 points
|
39 µs |
| Set CGRAM address |
0 |
0 |
0 |
1 |
a5 |
a4 |
a3 |
a2 |
a1
|
a0 |
Positionne le compteur d'adresse de la CGRAM**
|
39 µs |
| Set DDRAM address |
0 |
0 |
1 |
a6 |
a5 |
a4 |
a3 |
a2 |
a1
|
a0 |
Positionne le compteur d'adresse de la DDRAM
|
39 µs |
| Write data to CGRAM or DDRAM |
1 |
0 |
d7 |
d6 |
d5 |
d4 |
d3 |
d2 |
d1
|
d0 |
Write data to CGRAM : écrit la donnée (d7 ...d0) à l'adresse de la CGRAM définie par l'instruction précédente Set CGRAM address
Write data to DDRAM : écrit la donnée (d7 ...d0) à l'adresse de la DDRAM définie par l'instruction précédente Set DDRAM address
|
43 µs |
| Read Busy flag and address counter |
0 |
1 |
BF |
ac6 |
ac5 |
ac4 |
ac3 |
ac2 |
ac1 |
ac0 |
Lit le drapeau BF (Busy Flag) et le compteur d'adresse (ac6 ... ac0).
Le drapeau Busy est disponible sur la sortie DB7.
Quand le drapeau est au niveau 1, cela veut dire que le contrôleur est occupé à traiter une instruction.
Le contrôleur n'accepte aucune nouvelle instruction tant que le drapeau est au niveau 1 : il faut donc attendre que le drapeau passe au niveau 0.
|
- |
| Read data from CGRAM or DDRAM |
& |
1 |
d7 |
d6 |
d5 |
d4 |
d3 |
d2 |
d1 |
d0 |
Read data from CGRAM : lit la donnée (d7 ...d0) à l'adresse de la CGRAM définie par l'instruction précédente Set CGRAM address
Read data from DDRAM : lit la donnée (d7 ...d0) à l'adresse de la DDRAM définie par l'instruction précédente Set DDRAM address
|
43 µs |
X : 0 ou 1
* DDRAM = Display Data RAM
** CGRAM = Character Generator RAM
Les 2 derniers sont impossible car on ne peut lire le port.
Affichage
Pour afficher les caractères, il faut rentrer les valeurs ASCII correspondantes dans la DDRAM chaque case correspond a 1 caractère
La première ligne $00 et la seconde commence a $40 et on utilise les caractères ASCII.
Des caractères sont personnalisable mais je ne les ait jamais utilisé.
Mode 4 bits
Il existe 2 mode le mode 8 bits et le mode 4 bits , nous utiliseront le mode 4 bits qui permet de contrôler l'afficheur au complet sans avoir a utiliser plus d'un port.
Il faut tout d'abord le mettre en mode 4 bits. ( utiliser la fonction startlcd)
Ensuite, il y a des règles pour communiquer en mode 4 bits, on transmet les bits de poids fort ensuite les bits de poids faible ( c'est pourquoi le mode 4 bits est plus lent que le mode 8 bits)

Pour le programme , je ne me suis pas soucier des temps, l'I2C prend en moyenne 500 µs pour envoyer 1 octet. Donc normalement, je peux supprimer tous les delays.
Schéma

Comme on peux l'observer l'adresse du PCF8574P est : 0b01000000 , mais on peux la modifier ( en modifiant le typon )
Ce système est très bien quand il nous manque 1 port et évite d'avoir beaucoup de fils ou de grosses nappes qui se baladent...
Le typon

Le typon format PDF
Nomenclature
1 afficheur LCD 2 lignes
Un composant I2C PCF8574P
2 résistance de 10 K ( facultatif ) Car le Bus I2C utilise ses entrées à collecteur ouvert.
2 Bornier double. ( les remplacer par des autres types de connecteurs peux être ingénieux ...
1 connecteur HE14 1 rangée femelle ( à placer sur la carte )
1 connecteur HE14 1 rangée mâle ( à placer sur l'afficheur )
Programme
Le programme a été réaliser pour les pics avec le compilateur CSS. Pour un autre compilateur , ou un autre composant , il faudras modifier le programme.
#include <16f876A.h>
#fuses HS, NOWDT, NOPROTECT, NOPUT, NOBROWNOUT, NOLVP
#use delay (clock=20000000)
#use I2C(master, sda=PIN_C4, scl=PIN_C3)
#define addresse_LCD 0b01000000
//////////////////////////////////////////////////////////////////////////////
//Programme réaliser par Matthieu
//Janvier 2008
//
//Les fonctions :
//
// startlcd() // inisialise l'afficheur ( à placer au dépard)
// clear() // efface le contenu de l'afficheur
// ligne_suivante()//passage à la ligne suivante
// affich("Message")// affiche message.
// création de lcd_putc(message)
// f clear_lcd
// ligne_up
//
//
//
// Régle de cablage :
// D0> E
// D1> RS NEW R/W
// D2> R/W NEW : RS
// D3> NC
// D4> D4
// D5> D5
// D6> D6
// D7> D7
//
//////////////////////////////////////////////////////////////////////////////
void envoi(unsigned char data)
{
i2c_start();
i2c_write(addresse_LCD);//addresse du composant
i2c_write(data);
i2c_stop();
}
void valid_e(unsigned char data)
{
data=data|0b00000001;//E est a 1
envoi(data);
delay_ms(1);
data=data-1;//E=0
envoi(data);
delay_ms(1);
}
void startlcd()
{
//On travaille sur la commande donc RS=0 R/W=0 écriture
valid_e(0x00);
valid_e(0x10);
valid_e(0x00);
valid_e(0x00);
valid_e(0x10);
//Passage en mode 8 bit
valid_e(0x30);
valid_e(0x30);
// on passe en mode 4 bits
valid_e(0x30);
valid_e(0x20);
//mode 4 bits, 2 lignes, caractères 5x7 (28h)
valid_e(0x20);
valid_e(0x80);
//affichage en fonction, pas de curseur (0Ch)
valid_e(0x00);
valid_e(0xC0);
//le curseur se déplace vers la gauche (06h)
valid_e(0x00);
valid_e(0x60);
//on efface l'afficheur
valid_e(0x00);
valid_e(0x10);
}
void clear_lcd()
{
valid_e(0x00);
valid_e(0x10);
}
void ligne_up()
{
//40h
valid_e(0xC0);
valid_e(0x00);
delay_ms(1);
}
void affich(char mess)
{
//Le message passe lettre par lettre , donc cette fonction passe en boucle
char data;
data=mess&0xF0;
data=data+4; //RS a 1
valid_e(data);
data=mess&0x0F;
data=data<<4;
data=data+4;//RS a 1
valid_e(data);
}
void lcd_putc(char c)
{
switch(c)
{
case'\f':
clear_lcd();
break;
case'\n':
ligne_up();
break;
default:
affich(c);
break;
}
}
void main()
{
startlcd();
while(1)
{
lcd_putc("\fMon LCD\nI2C");
delay_ms(1000);
lcd_putc("\f");
lcd_putc("Fonctionne");
delay_ms(1000);
}
}
Photos



Une amélioration qui pourrais être bien: agrandir le typon et pouvoir ajouter des vis pour donner moins de choc aux fixations. Puis on pourrais facilement visser a l'aide d'une équerre notre LCD I2C sur notre robot.
Avertissement
L'I2C fonctionne à une certaine vitesse, si vous utilisez n'importe quelle câble vous risquez de vous faire avoir. Par exemple un câble RJ11 droit ne dois pas être trop long. Car 2 fils l'un à coté de l'autre forme un condensateur , et un condensateur forme un joli filtre passe bas.
Un système qui fonctionne bien : 4 fils avec un bornier.
Les fils de couleurs ou des dédompteurs peuvent vous éviter de griller vos composants ( s'est idiot , mais sous la précipitation ou tard le soir , s'est parfois utile)
Si vous souhaitez améliorer le système vous êtes prié d'en faire profité le plus de monde possible.
Remerciement
Je tiens a remercier les personnes sur internet qui ont fait un cour sur les afficheur LCD. Notament fabrice sincere, qui m'a permis d'utiliser son cour pour réaliser mon article.
Matthieu
|