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 connecteurSymboleTypeDescription
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.



  1. #include <16f876A.h>
  2. #fuses HS, NOWDT, NOPROTECT, NOPUT, NOBROWNOUT, NOLVP
  3. #use delay (clock=20000000)
  4. #use I2C(master, sda=PIN_C4, scl=PIN_C3)
  5. #define addresse_LCD 0b01000000
  6.  
  7. //////////////////////////////////////////////////////////////////////////////
  8. //Programme réaliser par Matthieu
  9. //Janvier 2008
  10. //
  11. //Les fonctions :
  12. //
  13. //         startlcd() // inisialise l'afficheur ( à placer au dépard)
  14. //         clear() // efface le contenu de l'afficheur
  15. //         ligne_suivante()//passage à la ligne suivante
  16. //         affich("Message")// affiche message.
  17. //         création de lcd_putc(message)
  18. //                       f clear_lcd
  19. //                       ligne_up
  20. //
  21. //
  22. //
  23. //         Régle de cablage :
  24. //                D0> E
  25. //                D1> RS  NEW R/W
  26. //                D2> R/W NEW : RS
  27. //                D3> NC
  28. //                D4> D4
  29. //                D5> D5
  30. //                D6> D6
  31. //                D7> D7
  32. //
  33. //////////////////////////////////////////////////////////////////////////////
  34.  
  35.  
  36.  
  37.  
  38. void envoi(unsigned char data)
  39.    {
  40.  
  41.    i2c_start();
  42.    i2c_write(addresse_LCD);//addresse du composant
  43.    i2c_write(data);
  44.    i2c_stop();
  45.    }
  46.  
  47. void valid_e(unsigned char data)
  48.    {
  49.    data=data|0b00000001;//E est a 1
  50.    envoi(data);
  51.    delay_ms(1);
  52.    data=data-1;//E=0
  53.    envoi(data);
  54.    delay_ms(1);
  55.    }
  56.  
  57. void startlcd()
  58.    {
  59.    //On travaille sur la commande donc RS=0 R/W=0 écriture
  60.    valid_e(0x00);
  61.    valid_e(0x10);
  62.    valid_e(0x00);
  63.    valid_e(0x00);
  64.    valid_e(0x10);
  65.    //Passage en mode 8 bit
  66.    valid_e(0x30);
  67.    valid_e(0x30);
  68.    // on passe en mode 4 bits
  69.    valid_e(0x30);
  70.    valid_e(0x20);
  71.    //mode 4 bits, 2 lignes, caractères 5x7 (28h)
  72.    valid_e(0x20);
  73.    valid_e(0x80);
  74.    //affichage en fonction, pas de curseur (0Ch)
  75.    valid_e(0x00);
  76.    valid_e(0xC0);
  77.    //le curseur se déplace vers la gauche (06h)
  78.    valid_e(0x00);
  79.    valid_e(0x60);
  80.    //on efface l'afficheur
  81.    valid_e(0x00);
  82.    valid_e(0x10);
  83.    }
  84.  
  85. void clear_lcd()
  86.         {
  87.    valid_e(0x00);
  88.    valid_e(0x10);
  89.         }
  90. void ligne_up()
  91.    {
  92.    //40h
  93.    valid_e(0xC0);
  94.    valid_e(0x00);
  95.    delay_ms(1);
  96.    }
  97.  
  98. void affich(char mess)
  99.          {
  100.           //Le message passe lettre par lettre , donc cette fonction passe en boucle
  101.           char data;
  102.           data=mess&0xF0;
  103.           data=data+4; //RS a 1  
  104.           valid_e(data);
  105.           data=mess&0x0F;
  106.           data=data<<4;
  107.           data=data+4;//RS a 1
  108.           valid_e(data);
  109.  
  110.          }
  111.  
  112. void lcd_putc(char c)
  113.    {
  114.    switch(c)
  115.           {
  116.           case'\f':
  117.                  clear_lcd();
  118.                  break;
  119.           case'\n':
  120.                  ligne_up();
  121.                  break;
  122.           default:
  123.                  affich(c);
  124.                  break;
  125.           }
  126.    }
  127.  
  128.  
  129.  
  130. void main()
  131.    {
  132.    startlcd();
  133.    while(1)
  134.           {
  135.           lcd_putc("\fMon LCD\nI2C");
  136.           delay_ms(1000);
  137.           lcd_putc("\f");
  138.           lcd_putc("Fonctionne");
  139.           delay_ms(1000);
  140.           }
  141.    }
  142.  


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

© robot-amateur.com - Tous droits réservés. Reproduction interdite sans autorisation.