Les afficheurs LCD interface I2C
et les picaxes
On trouve sur la toile des afficheurs LCD équipés d'adaptateur I2C types PCA8574 ou PCF8574, ou de petites cartes adaptateurs pour un ou deux euros.
Ce sont des "expandeurs de bits", ils reçoivent un octet sur l'entrée I2C et le ventile sur 8 sorties.
Bloc diagramme:
Ce bloc diagramme présente les 16 broches des CI PCF8574 implantés sur ces adaptateurs:
Les broches SDA, SCL, Vdd, Vss (GND) que l'on retrouve sur le connecteur.
Les broches A0, A1, A2, permettant d'adapter l'adresse I2C si elles sont accessibles et modifiables.
Pour le PCF8574A, les adresses sont différentes:
L'adresse sur 7 bits par défaut est donc $20 (%100000), mais les commandes picaxe hi2csetup demandent une adresse sur 8 bits, même si le dernier bit (R/W) est automatiquement ajusté en fonction des commandes (hi2cin et hi2cout).
En général, la commande sera donc:
hi2csetup i2cmaster,%01000000, i2cslow, i2cbyte
Mais attention aux surprises, sur certains drivers A0, A1, A2 peuvent être reliés à Vcc et l'adresse devient : %01001110 (ou $4E).
Enfin, les broches P0 à P7 repésentent les bits (bit0 à bit7) de l'octet lu sur l'entrée I2C.
Les liaisons entre le PCF8574 et LCD relevées sur mon afficheur avec adaptateur intégré :

Remarques:
Le dernier bit de l'octet (P0) indique si l'octet est une commande (0) ou une donnée (1)
P1 est relié à R/W, normalement, R/W est toujours à 0v
P2 est relié à E, validation des données présentes sur les entrées du LCD
P3 commande le rétroéclairage, doit rester à 1 pour que le LCD reste allumé
P4 à P7 sont reliés à D4, D7, entrées du LCD en mode 4 bits.
Les autres entrées D0,D4 sont ici reliées à Vdd, leurs niveaux sont indifférents.
Il y a en général un cavalier pour court circuiter le transistor contrôlant le rétroéclairage, absent sur mon afficheur 2004 tout équipé.
Compte tenu de tout cela, il n'y a plus de problèmes, il faut fabriquer l'octet que le LCD attend pour une utilisation en mode parallèle 4 bits.
Voir les détails de l'initiation du LCD sur cette page, les données sont maintenant logées dans des "lookup", et non en EEPROM qui reste entièrement libre pour d'autres utilisations.
Et pour le positionnement des curseurs, voir aussi cette page.
Modif 04/05/15 et 30/10/15: amatpicax59 m'a fait part d'un problème dépendant de la vitesse horloge.
Voici les modifications apportées dans le programme en fin de page:
- i2cfast est modifié en i2cslow_XX, avec XX = fréquence horloge (comme dans la doc, c'est mieux...).
- Les résistances de pullup sont activées sur C.1 et C.2 (broches i2c), ce qui permet de supprimer les deux résistances de 4k7.
- Enfin, le plus important, ajout du masque &%1011, pour ramener le pulse E au niveau bas (sinon, le dernier caractère n'est pas affiché, merci GM39). Il faut l'ajouter dans les copier-coller ci dessous, la modif est dans le dernier programme en fin de page. Schéma du test, il n'y a pas de potentiomètre sur C.4 pour cet essai d'affichag

Le code d'essai:
;Utilisation expandeur PCF8574 sur LCD MM 19082017
;Teste minimum LCD1602
; SCL sur C.1
; SDA sur C.2
#picaxe 08M2
dirsC =%000111
symbol rsbit=bit0
symbol cpt=b1
symbol car=b2
symbol dat=b3
symbol vari= w13
setfreq M32
; Initialisation I2C 4 bits , etc ********
hi2csetup i2cmaster,%01001110, i2cslow_32, i2cbyte
; Initialisation LCD *********
for cpt=0 to 5
lookup cpt,($33,$32,$28,$c,$6,$01),car
gosub EnvoiByteCommInit
next
pause 100 ;temps init du LCD
; Affichage texte ***********************
car= 128 'curseur début ligne1
gosub EnvoiByteComm
for cpt=0 to 6
lookup cpt,("Bonjour"),car
GOSUB EnvoiByteData
next
car= 192 'curseur ligne2
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,("Enfin !!"),car
GOSUB EnvoiByteData
next
do loop ;boucle d'arret programme
; Sub envoi vers LCD via I2C *************
EnvoiByteCommInit:
pause 15
EnvoiByteComm:
rsbit=0
EnvoiByteData:
;1ère moitié
dat=car & $F0 | %1000 | rsbit ;%1000 pour l'?clairage
hi2cout (dat)
pause 2
dat=dat | %1100
hi2cout (dat) ;pulse sur E cad P2
pause 2 ;pause 2 pour 32 MHz
dat=dat | %1000 ;fin pulse
hi2cout (dat)
pause 2
;2ème moitié
dat=car & $0F * 16 | %1000 | rsbit
hi2cout (dat)
pause 2
dat=dat | %1100
hi2cout (dat)
pause 2
dat=dat | %1000 & %1011
hi2cout (dat)
rsbit=1
return
La récompense:
Petite variante pour afficher une variable:
En fait, c'est le shéma du test précédent avec en plus un potentiomètre sur C.4 pour lire une tension de 0 à 5 V.
Résultat:
La précision de la tension mesurée est de l'ordre de 1%.
Et les accents sur un LCD chinois? La description des caractères en CGRAM a été abordée dans cette page, nous y revenons ici avec une méthode plus compacte.
Les caractères sont décrits dans une matrice de 5 x 8 pixels (visibles sur la photo ci dessus), la ligne du bas est généralement réservée au curseur. Pour les miniscules, nous pouvons utiliser les lignes libres en haut et en bas.
Description du caractère "é", que vous reconnaîtrez en tassant les lignes. ...X. => 00010 = $2 = 2
..X.. => 00100 = $4 = 4
.XXX. => 01110 = $E = 14
X...X => 10001 = $11 = 17
XXXXX => 11111 = $1F = 31
X.... => 10000 = $10 = 16
.XXX. => 01110 = $E = 14
..... => 00000 = $0 = 0
Nous utiliserons finalement le notation décimale, plus compacte sans préfixe.
La commande pour programmer la CGRAM est:
X*8|$40, ou X est la mémoire utilisée, variable de 1 à 8, cette commande indique au LCD que les 8 octets suivants décrivent le caractère placé en mémoire X de la CGRAM
La description du caractère "é" en mémoire 1 de la CGRAM s'écrit: car=1*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(2,4,14,17,31,16,14,0),car
gosub EnvoiByteData
next L'utilisateur peut ainsi inventer et décrire tout caractère non disponible dans la table de caractères du LCD.
Voici la description de 8 nouveaux caractères français: - é => (2,4,14,17,31,16,14,0)
- è => (8,4,14,17,31,16,14,0)
- ê => (4,10,14,17,31,16,14,0)
- à => (8,4,14,1,15,17,15,0)
- ç => (0,14,16,16,17,14,4,12)
- ù => (8,4,17,17,17,19,13,0)
- ü => (10,0,17,17,17,19,13,0)
- ë => (10,0,14,17,31,16,15,0)
Le code complet, avec 8 nouveaux caractères (modf 04/05/2015):
(modif 30/10/15 erreur corrigée par GM39)
Pour l'I2C, placer deux résistances de 4k7 sur C.1 et C.2, cf schéma ci dessus
;Utilisation expandeur PCF8574 sur LCD MM 04 05 2015
;Ecriture de textes, variables, accentués
; SCL sur C.1
; SDA sur C.2
; tension var sur C.4
#picaxe 08M2
dirsC =%000111
symbol rsbit=bit0
symbol cpt=b1
symbol car=b2
symbol dat=b3
symbol vari= w13
setfreq M32
; Initialisation I2C 4 bits , etc ********
hi2csetup i2cmaster,%01001110, i2cslow_32, i2cbyte
; Initialisation LCD *********
for cpt=0 to 5
lookup cpt,($33,$32,$28,$c,$6,$01),car
gosub EnvoiByteCommInit
next
pause 100 ;temps init du LCD
gosub cardef ;si on veut des accents ou des caractères spéciaux..
; Affichage texte ***********************
car= 132 'curseur début ligne1
gosub EnvoiByteComm
for cpt=0 to 6
lookup cpt,("Bonjour"),car
GOSUB EnvoiByteData
next
car= 196 'curseur ligne2
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,("Enfin !!"),car
GOSUB EnvoiByteData
next
car=212 'curseur début ligne 4
gosub EnvoiByteComm
for cpt=0 to 16
lookup cpt,("variable = V"),car
GOSUB EnvoiByteData
next
; Affichage accentués ********************
car=148
gosub EnvoiByteComm
for cpt=0 to 16
lookup cpt,("accentu",1,"s"," ",2,3,4,5,6,7,8),car
GOSUB EnvoiByteData
next
; Affichage variable actualisée **********
do
car= 223 'curseur ligne 4
gosub EnvoiByteComm
readadc10 C.4,vari
vari= vari*50/102 ;mise é l'échelle avec approximation
bintoascii vari,b6,b6,b6,b5,b4 ;on a besoin que de 3 chiffres
for cpt=0 to 3
lookup cpt,(b6,",",b5,b4),car
GOSUB EnvoiByteData
next
loop
cardef: ; définition des caractéres ajoutés en CGRAM
; def du é **************************
car=1*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(2,4,14,17,31,16,14,0),car
gosub EnvoiByteData
next
; def du è ***************************
car=2*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(8,4,14,17,31,16,14,0),car
gosub EnvoiByteData
next
;def du ê *****************************
car=3*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(4,10,14,17,31,16,14,0),car
gosub EnvoiByteData
next
;def du à *****************************
car=4*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(8,4,14,1,15,17,15,0),car
gosub EnvoiByteData
next
;def du ç *****************************
car=5*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(0,14,16,16,17,14,4,12),car
gosub EnvoiByteData
next
;def du ù *****************************
car=6*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(8,4,17,17,17,19,13,0),car
gosub EnvoiByteData
next
;def du ü ******************************
car=7*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(10,0,17,17,17,19,13,0),car
gosub EnvoiByteData
next
;def du ë ******************************
car=8*8|$40
gosub EnvoiByteComm
for cpt=0 to 7
lookup cpt,(10,0,15,17,31,16,15,0),car
gosub EnvoiByteData
next
return
; Sub envoi vers LCD via I2C *************
EnvoiByteCommInit:
pause 15
EnvoiByteComm:
rsbit=0
EnvoiByteData:
;1ére moitié
dat=car & $F0 | %1000 | rsbit ;%1000 pour l'éclairage
hi2cout (dat)
pause 1
dat=dat | %1100
hi2cout (dat) ;pulse sur E cad P2
pause 1
dat=dat | %1000 & %1011 ;fin pulse
hi2cout (dat)
pause 1
;2éme moitié
dat=car & $0F * 16 | %1000 | rsbit
hi2cout (dat)
pause 1
dat=dat | %1100
hi2cout (dat)
pause 1
dat=dat | %1000 & %1011
hi2cout (dat)
rsbit=1
return
Résultat de l'opération: (un pixel de trop sur le à, c'est corrigé!) 