Interfaçage d'un écran LCD

Cet article traite essentiellement des modules LCD basé sur le controleur Hitachi 44780 ou equivalent.

Description des pins
N° Pin Symbole Niveau Fonction
1 Vss GND Ground
2 Vcc +5V Module Power
3 Vee Contraste Liquid Cristal Contrast
4 RS H/L Register select, H=data, L=instruction
5 R/W HL Read/Write, H=read (LCD->CPU), L=write (CPU->LCD)
6 E Note 1 Edge-sensitive Enable
7 DB0 Note 2 Data bit 0 (least significant bit)
8 DB1 Note 2 ''
9 DB2 Note 2 ''
10 DB3 Note 2 ''
11 DB4 Note 2 ''
12 DB5 Note 2 ''
13 DB6 Note 2 ''
14 DB7 Note 2 ''
NOTE 1: E (Enable) latche RS et R/W sur le front montant et latche les données sur le flans descendant. Selon les specs, RS et R/W doivent être stable avant que E soit à l'état haut et doivent rester stable jusqu'à ce que E passe à l'état bas. Les données doivent être stable quand E passe à l'état bas.

NOTE 2: Les pins de données DB7-DB0 (ou DB7-DB4 quand on utilise une interface à 4-bits) sont controllées par le CPU lors de l'écriture, mais doivent être mise en état de haute impédance afin que le module puisse controller les lignes lors d'une lecture ou quand on utilise le controle par BUSY FLAG.

Quand on utilise une interface à 4-bits, Le quartet de poids fort est écrit en premier (bit7-bit4), alors que le quartet de poids faible est écrit (bit3-bit0) lors du cycle Enable suivant (Pas de délai nécessaire entre les deux instructions). les lignes DB3 à DB0 sont laissées déconnectées. Les pins ont des pullups internes donc pas de problèmes si on les laisse déconnectées.

Le jeu de charactères :
Le set d'instructions :

Attention, toutes les instructions n'ont pas le même temps d'execution ! Il faut donc leur laisser le temps...
Temps d'execution des instructions
Instruction Temps d'execution Remarque
Clear display 1.64ms /
Home cursor 40us à 1.64ms Dépends de la "distance" du curseur par rapport à l'origine
Read busy flag 1 Enable cycle 2 cycles si mode 4 bits
Character generator read/write 120us /
Toutes les autres instructions 40 us /

Ces délais d'execution signifient qu'il faut, après une opération, que le CPU surveille le Busy Flag ou si la connection CPU-module LCD est du type Write only que l'on respecte les temps d'exécution avant de lancer l'instruction suivante. Si on veut améliorer la vitesse de communication, il est recommandé d'utiliser la méthode Busy Flag plutot que celle des délais.
Comment adresser la mémoire :
La RAM du Character generator se trouve aux adresses 64-127 et RAM écran se trouvent aux adresses 128-255. C'est juste un artifice, Les blocks de la RAM ne sont pas physiquement contigus.

Comment utiliser des caractères propres à l'utilisateur :

L'écran possède 64 bytes de CG RAM où on peut stocker 8 caractères définisables par l'utilisateur. Chacun de ces caractères sont définis comme des caratères 5X8 dans une matrice 8x8. La partie 5X8 est justifiée à droite dans la matrice. Notez quand même que dans le mode 5X10, on ne peut stocker que 4 caractères utilisateur utilisant 11 bytes chacun.
Adresses CG Données CG
D7 D6 D5 D4 D3 D2 D1 D0
x+0 x x x 1 1 1 1 1 *****
x+1 x x x 1 0 0 0 0 *
x+2 x x x 1 0 0 0 1 **
x+3 x x x 1 1 1 1 1 *****
x+4 x x x 1 0 0 0 1 **
x+5 x x x 1 0 0 0 0 *
x+6 x x x 1 0 0 0 0 *
x+7 x x x 0 0 0 0 0 ( ligne du curseur)
Où "x" l'adresse du caractère : CG0=0, CG1=8, CG2=16, CG3=24, CG4=32, CG5=40, CG6=48, CG7=56. Comme on peut le voir dans le tableau ci-dessus, chaque byte de données CG représente 1 ligne de pixel du caractère avec D0 comme le pixel le plus à droite et D4 le plus à gauche (les 3 bits supérieurs ne sont pas affichés). La première adresse du caractère représente la ligne supérieure et la 7ième la ligne du bas. (La 8ième est "ORed" avec la ligne de curseur). Un '1' sur n'importe quelle position de pixel devient un pixel "noir" sur l'afficheur.
La CG RAM occupe un espace mémoire différent de l'espace de donnée de la (DD) RAM. On doit d'abord mettre la première adresse CG avant d'écrire une donnée CG. Chaque écriture incrémente/décrémente automatiquement le pointeur d'adresse CG RAM. N'oubliez pas de repasser en mode d'adressage de la RAM DD avant d'envoyer des caractères à afficher...
Comment adresser la mémoire écran :
Dans la liste ci-dessous, "ligne 1" est la ligne supérieure et "ligne n" est la ligne la plus basse sur l'écran. Sur chaque ligne, le caractères le plus à gauche a l'adresse la plus basse. Les adresses s'accroissent quand on va vers la droite. De plus, les adresses DD RAM sont indiquées sans le bit 80h à l'état haut. Ajoutez 80h à l'adresse du caractère pour faire la commande "Display Data RAM Address Set ".
Les modules 16x2 sont constitués de 2 lignes de 16 caractères. Les adresses de la ligne 1 sont situées de 00h à 0Fh (0 à 15). Les adresses de la ligne 2 sont situées de 40h à 4Fh (64 à 79).
|00|01|02|03|04|05|06|07|08|09|0A|0B|0C|0D|0E|0F|
|40|41|42|43|44|45|46|47|48|49|4A|4B|4C|4D|4E|4F|
La RAM écran est constituée de 80 bytes quelque soit le nombre de caractères affichable par le module. Ces extra bytes peuvent être utilisés quand le scrolling de l'écran est employé ou pour stocker des données en provenance du CPU (de la RAM externe supplémentaire !). Il n'y a pas de RAM dans les blocks 28h-3Fh et 68h-7Fh.
L'initialisation des modules :
Les modules avec un controleur Hitachi s'initiera de lui-même si Vcc s'éleve de 0 à 4.5v en une periode de .1mS à 10mS (sinon, on peut utiliser un circuit RC). Si vous utilisez l'auto-initialisation, le module era dans les modes suivants : interface 8-bits, caractères 5x7, increment du curseur vers la droite, sans glissement.
Initialisation en interface 8-bits
POWER ON

Wait 15ms

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 x x x x x=don't care
Set 8-bit mode
Wait 4.1ms

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 x x x x Set 8-bit mode

Wait 100us

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 x x x x Set 8-bit mode

Wait 4.1ms

Busy Flag cannot be checked before this point

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 1 F x x 8-bit operation
1/16 duty cycle
F=font,
1 for 5x11 dot matrix
0 for 5x8 dot matrix
Wait 40us

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 1 0 0 0 Display off,
cursor off,
blink off
Wait 40us

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 1 1 C B Display on,
C=1 for cursor on
B=1 for blinking cursor
Wait 1.64m

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 0 1 I S Set entry mode
I=1 for cursor move to
the right, I=0 for
cursor move to the left
S=1 for shift display,
S=0 for no shift
Wait 40us

INITIALIZATION COMPLETE

NOTE: Remember to turn the display back on and set up the cursor
as desired with an On/Off Control command.

Initialisation pour interface 4-bits
Le module s'allume en mode 8-bits. Les instructions de démarrage sont envoyées en mode 8-bits, les 4 bits (non connectés) ne sont pas utilisés. Après la quatrième instruction, qui fait passer le module en mode 4-bit, les bytes de controle sont envoyés suivant les cycles enable consécutifs (pas de delais nécessaires entre les quartets). Le quartet de poids fort est envoyé d'abord suivi immédiatement du quartet de poids faible.
POWER ON

Wait 15ms

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 n/c n/c n/c n/c n/c=not connected
set 8-bit mode
Wait 4.1ms

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 n/c n/c n/c n/c set 8-bit mode

Wait 100us

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 1 n/c n/c n/c n/c set 8-bit mode

Wait 4.1ms

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 1 0 n/c n/c n/c n/c set 4-bit operation

Wait 40us

Busy Flag cannot be read before this point

RS R/W DB7 DB6 DB5 DB4
0 0 0 0 1 0

0 0 1 F x x 4-bit operation
1/16 duty cycle
F=font, 1 for 5x11 dot matrix
0 for 5x8 dot matrix
x=don't care

Wait 40us

RS R/W DB7 DB6 DB5 DB4
0 0 0 0 0 0

0 0 1 0 0 0 Display off, cursor off, blink off

Wait 40us

RS R/W DB7 DB6 DB5 DB4
0 0 0 0 0 0

0 0 1 1 C B Display on, C=1 for cursor on,
B=1 for blinking cursor
Wait 1.64ms

RS R/W DB7 DB6 DB5 DB4
0 0 0 0 0 0

0 0 0 1 I S Set entry mode, I=1 for cursor moving
right, I=0 for cursor moving left,
S=1 for shift display, S=0 for no shift
Wait 40us

INITIALIZATION COMPLETE

Voici un exemple de code utilisé pour un module LCD à 2 lignes attaché au port P1 d'un 8051 en mode 4-bits avec un interface en write-only. D7-D4 sont reliés à P1.7-P1.4, RS à P1.3,et E à P1.2. R/W est mis à la masse.
LCD51.ASM
---------
$MOD51

; SIMPLE ROUTINES FOR DRIVING LCD DISPLAY WITH 8751
; by CHRIS BURIAN

LCD_PORT EQU P1
E_PIN EQU P1.2

CLS EQU 00000001b

D_SET EQU 00001000b
E_SET EQU 00000100b
F_SET EQU 00100000b

D_ON EQU 00000100b
D_OFF EQU 00000000b
C_ON EQU 00000010b
C_OFF EQU 00000000b
B_ON EQU 00000001b
B_OFF EQU 00000000b

S_NO EQU 00000000b
S_YES EQU 00000001b
C_INC EQU 00000010b
C_DEC EQU 00000000b

F_8BIT EQU 00010000b
F_4BIT EQU 00000000b
F_2LINE EQU 00001000b
F_1LINE EQU 00000000b
F_8FONT EQU 00000000b
F_11FONT EQU 00000100b

CG_ADDR EQU 01000000b
DD_ADDR EQU 10000000b

ORG 0h ;reset vector
LJMP MAIN

ORG 30h ;code starts after vector table

;transmit character in ACC to LCD

CHAR_OUT:
PUSH ACC ;store the byte
ANL A, #11110000b ;mask out low nibble
ORL A, #00001000b ;set RS=1

MOV LCD_PORT, A ;send high order nibble
SETB E_PIN ;toggle Enable
CLR E_PIN

POP ACC ;get low order nibble
SWAP A ;put in high nibble
ANL A, #11110000b ;mask out nibble
ORL A, #00001000b ;set RS=1

MOV LCD_PORT, A ;send low order nibble
SETB E_PIN ;toggle Enable
CLR E_PIN

ACALL WAIT_40U ;pause for 40us
RET

;transmit command in ACC to LCD

COMD_OUT:
PUSH ACC ;store the byte
ANL A, #11110000b ;mask out low nibble
;RS=0

MOV LCD_PORT, A ;send high order nibble
SETB E_PIN ;toggle Enable
CLR E_PIN

POP ACC ;get low order nibble
SWAP A ;put in high nibble

NIBBLE_OUT:
ANL A, #11110000b ;mask out nibble
ORL A, #00001000b ;set RS=1

MOV LCD_PORT, A ;send low order nibble
SETB E_PIN ;toggle Enable
CLR E_PIN

ACALL WAIT_40U ;pause for 40us
RET


;initialize the LCD

INIT_LCD:
ACALL WAIT_15M ;pause for 15ms
MOV A, #(F_SET OR F_8BIT) ;set 8-bit mode
ACALL NIBBLE_OUT ;send to LCD
ACALL WAIT_5M ;pause for 4.1ms

MOV A, #(F_SET OR F_8BIT) ;set 8-bit mode
ACALL NIBBLE_OUT ;send to LCD
ACALL WAIT_60U ;pause for 60us extra

MOV A, #(F_SET OR F_8BIT) ;set 8-bit mode
ACALL NIBBLE_OUT ;send to LCD
ACALL WAIT_5M ;pause for 4.1ms

MOV A, #(F_SET OR F_4BIT) ;set 4-bit mode
ACALL NIBBLE_OUT ;send to LCD

;set 4-bit, 2-line, 5x8 font
MOV A, #(F_SET OR F_4BIT OR F_2LINE OR F_8FONT)
ACALL COMD_OUT ;send to LCD

;turn off display, cursor, blink
MOV A, #(D_SET OR D_OFF OR C_OFF OR B_OFF)
ACALL COMD_OUT ;send to LCD

;turn on display and cursor
MOV A, #(D_SET OR D_ON OR C_ON OR B_OFF)
ACALL COMD_OUT ;send to LCD

;cursor moves right, no shift
MOV A, #(E_SET OR S_NO OR C_INC)
ACALL COMD_OUT ;send to LCD

RET ;initialization complete

; send a message string to the LCD

PRINT_LCD:
MOV A, #0 ;clear ACC
MOVC A, @A+DPTR ;fetch letter
INC DPTR
CJNE A,#16,PT_1 ;strings end with 16,
SJMP PT_DONE ; finished

PT_1:
ACALL CHAR_OUT ;send letter to LCD
SJMP PRINT_LCD ;repeat loop

PT_DONE:
RET

; program character generator RAM

PROG_LCD:
PUSH 1 ;save register R1
MOV R1,#8 ;8 bytes in a character

MOV B, #8
MUL AB ;multiply char# by 8 to
; get CG RAM address
ORL A, #CG_ADDR ;set addr command
ACALL COMD_OUT ;send to LCD

PG_1:
MOV A, #0 ;clear ACC
MOVC A, @A+DPTR ;fetch row
INC DPTR
ACALL CHAR_OUT ;send row to LCD
ACALL WAIT_80U ;pause extra 80us

DJNZ R1, PG_1 ;send 8 rows total

POP 1 ;restore register R1
MOV A, #DD_ADDR ;go back to display RAM
ACALL COMD_OUT ;send to LCD

RET

;40 microsecond delay, assumes 12MHz or slower clock

WAIT_40U:
PUSH 1
MOV R1, #40
DJNZ R1, $
POP 1
RET

WAIT_60U:
PUSH 1
MOV R1, #60
DJNZ R1, $
POP 1
RET

WAIT_80U:
PUSH 1
MOV R1, #80
DJNZ R1, $
POP 1
RET

; 1 millisecond delay
WAIT_1M:
PUSH 1
PUSH 2
MOV R2, #4
W1LP: MOV R1, #250
DJNZ R1, $
DJNZ R2, W1LP
POP 2
POP 1
RET

WAIT_2M:
PUSH 1
MOV R1, #2
W2LP: ACALL WAIT_1M
DJNZ R1, W2LP
POP 1
RET
WAIT_5M:
PUSH 1
MOV R1, #5
W5LP: ACALL WAIT_1M
DJNZ R1, W5LP
POP 1
RET

WAIT_15M:
PUSH 1
MOV R1, #15
W15LP: ACALL WAIT_1M
DJNZ R1, W15LP
POP 1
RET

;initialize the LCD, program a custom character, and print
;out a message.

MAIN:
ACALL INIT_LCD

MOV DPTR, #SMILEY ;load custom character addr
MOV A, #1 ;put into custom char #1
ACALL PROG_LCD

MOV A, #CLS ;clear display, home cursor
ACALL COMD_OUT
ACALL WAIT_2M ;pause 1.64ms

MOV DPTR, #MSG1 ;load message address
ACALL PRINT_LCD

MOV A, #(DD_ADDR+40h) ;go to second line
ACALL COMD_OUT

MOV DPTR, #MSG2
ACALL PRINT_LCD

DONE: SJMP DONE

;cheesy smiley face
; ###
; # # #
; #####
; # # #
; # #
; #####
; ###

SMILEY:
DB 00001110b
DB 00010101b
DB 00011111b
DB 00010101b
DB 00010001b
DB 00011111b
DB 00001110b
DB 00000000b

MSG1:
DB 1,' Hello, World. ',1,16

MSG2:
DB 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16

;16 was chosen as the message delimiter because it is
;not a valid character number and won't ever be sent
;to the LCD to be displayed.

END
----- end -----