LCD1602 (HD44780)

Page principale

Avec un Amega8

Avec un arduino

Avec un module I²C (I2C)

Synthèse finale : Aout 2014.

Cet afficheur LCD est très pratique, fiable, esthétique, dont la luminosité et le contraste sont réglable. Vendu tel quel, il y a 16 bornes à souder, mais pour un usage « simple » seul 10 bornes suffisent.
En définitive, je ne l'utilise plus qu'avec un arduino (mini pro).
Il coûte présentement 1,48€ livré sur Ebay.

Avec un Atmega8 :
Débuté le 18 Avril 2013.

J'ai acheté ce module sur Ebay en chine, il y a quelques semaine à environs 1,8€ livré.
Mon but était de programmer ce module avec un microcontrôleur Amega8.

Compte-rendu :
Après quelques tests, j'ai compris que la source de mes looongues difficultés était le contraste des caractères. En effet, même un code est illisible si le contraste n'est pas correct.

Pour rêgler le Contraste : la tension à envoyer sur la borne N°3 : VO est autour de 1V (entre 0,5 et 1,5V). Donc, ne pas hésiter, mettre un potentiomètre, sinon, les difficultés sont presque garanties !
Rétro-éclairage :
Ma résistance de limitation de courant de la diode de rétro-éclairage est de 55ohm. C'est parfait. Attention, la puissance dissipée est de 0,5W, donc penser à mettre une résistance qui le supporte. (Edit du 15/06/2013 : il y a une résistance en série de 100ohm incorporée... Il n'y a plus qu'à mettre 5V sur l'anode et la cathode à GND...pffff !)
Démarrage :
Difficultés au niveau du démarrage : quelques fois, en branchant l'alimentation, la première ligne du LCD reste blanche, comme si mon code n'avait pas été pris en compte. Je cherche encore les raisons mais il est probable que ce soit la durée de misse sous tension. Après avoir mis 200 mS de temporisation au démarrage, ça marche déjà beaucoup mieux... Je pense que ça viens de là car lorsque j'avais ce fameux affichage blanc (uniquement la ligne du haut) je débranchais, une fois l'écran éteint, je rebranchais aussitôt et l'écran fonctionnait alors toujours parfaitement. Les condensateurs n'étant pas vide, la montée de tension devait être plus rapide, donc ce pourrait expliquer ceci... A vérifier. En tout cas, avec mes 200mS, je n'ai pas encore eu de problèmes.

Plus tard... J'ai encore des problèmes : la ligne du haut reste blanche lorsque le transfo est vraiment vide au démarrage (vide manuelle des condensateurs). De plus, en visualisant avec mon "oscilloscope maison" ce n'est pas une question d'alimentation. L'alimentation doit atteindre les 5V en mois de 200µS, et le µC démarre encore plus vite. Donc, j'ai fait exécuter la routine d'initialisation trois fois consécutivement, ça marche, mais seulement, l'info ne s'affiche que 1 à 1,5 seconde plus tard... Une éternité ! Mais ça semble marcher dans toutes les situations (je l'ai testé sur trois transfos, dont un très parasité, et j'y ai mis des faux contacts pour voir) il affiche toujours avec un peu plus d'une seconde après la mise sous tension... A déterminer la raison !

Pfff j'ai encore eu le même problème au démarrage... je ne sais pas comment le résoudre... Il y a peut-être une temporisation qui est à la limite... je vais les modifier.
Ajout d'un gros condensateur sur les 5V et de douze initialisations, toujours la même chose... Haaa ! J'ai peut-être une solution ! J'ai observé que lorsque l'écran ne fonctionnait pas, dernièrement, il n’apparaissait plus la fameuse ligne blanche mais un simple écran bleu. On en déduit, déjà, que le fait d'exécuter plusieurs initialisations à la suite devait fonctionner le démarrage correct. Ensuite, pour l'écran bleu, ça signifie qu'il ne prend pas en compte le signal d'écriture des lettres. Je le répète donc toutes les secondes. (Comme le reset de l'écran prends 2mS, on ne peut pas le faire trop rapidement, parce que ça se voit (tests toutes les 20mS)). Mes problèmes, semblent, globalement, être due aux "prise en compte" des signaux, et ça ne vient pas des temporisations car en les augmentant, les problèmes étaient les même. Et pour l'heure, je n'en ai plus... L'expérience le dira ! Un peu plus tard : ça fonctionne apparemment bien !

20 Mai 2013 :
Nouveaux tests car problèmes à la mise sous tension. J'ai finit par m’apercevoir que mon timing 20ms était en faits à 2mS... Maintenant, il démarre directement mais les chiffres ne s'affichent plus...Sauf que des fois, il met 4 à 5 secondes à afficher le texte (c'est à dire, effacer la ligne 1 toute noire et afficher mon texte...) inconcevable. Et les chiffres ne s'affichent jamais...Ha... je crois que la ligne du bas ne fonctionne plus du tout en faits... J'ai sans doute grillé quelque chose...

Ci-dessous, des infos glanées sur le web puis le code ASM pour Atmega8.

Branchement physique

Un module HD44780 comporte 16 bornes (dont les 2 dernières sont optionnelles si l'écran piloté ne dispose pas d'un rétroéclairage) :

Borne

Symbole

Type

Fonction

1

Vss

Alim

Masse 0V

2

Vcc

Alim

Alimentation générale 5V

3

Vee

Alim

Alimentation du panneau LCD (Contraste des caractères)

VLCD = VDD – V0

V0 = VDD → VLCD = 0 → Caractères invisibles

V0 = 0 → VLCD = VDD → Contraste maximum

4

RS

Entrée

RS = 1 → Sélection du registre de données

RS = 0 et R/W = 1 → Sélection du registre d’instruction

RS = 0 et R/W = 0 → Sélection du drapeau BUSY et du compteur d’adresse

5

R/W

Entrée

R/W = 0 → Mode écriture

R/W = 1 → Mode lecture

6

E

Entrée

Entrée de validation

Les entrées RS et R/W sont lues sur le front montant, et le bus de données est lu sur le front descendant.

7

D0

Entrée/Sortie

Bus de données, bit n°0 (LSB)

8

D1

Entrée/Sortie

Bus de données, bit n°1

9

D2

Entrée/Sortie

Bus de données, bit n°2

10

D3

Entrée/Sortie

Bus de données, bit n°3

11

D4

Entrée/Sortie

Bus de données, bit n°4

12

D5

Entrée/Sortie

Bus de données, bit n°5

13

D6

Entrée/Sortie

Bus de données, bit n°6

14

D7

Entrée/Sortie

Bus de données, bit n°7 (MSB)

15

A

Alim

Anode du système de rétro-éclairage (à alimenter en 5V à travers une résistance de 50 à 100Ω pour limiter le courant à 100mA)

16

K

Alim

Cathode du système de rétro-éclairage (masse)

Commande

En mode 8 bits

Dans ce mode, l’octet contenant les données est envoyé à l'afficheur (ou lu par l'afficheur) directement sur les broches D0 à D7.

En mode 4 bits

Dans ce mode, on n’utilise que les broches D4 à D7, les broches D0 à D3 doivent être connectées à la masse.

L’octet de données est envoyé (ou lu) en 2 fois :

Timings à respecter

(notes personnelles : il s'agit des valeurs minimum...)


En écriture


Temps à respecter en écriture pour le HD44780

En lecture

Temps à respecter en écriture pour le HD44780

Instructions de contrôle et d’affichage

Instructions

RS

R/W

DB7

DB6

DB5

DB4

DB3

DB2

DB1

DB0

Description

Durée

Clear display

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 à 00h)

> 1.64 ms

Return home

0

0

0

0

0

0

0

0

1

-

Place le curseur dans la position d'origine (1ère position à gauche, 1ère ligne : compteur d'adresse à 00h)

> 1.64 ms

Entry set mode

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é
Attention le décalage de l'affichage (S = 1) décale également les adresses de l'afficheur de sorte que l’adresse 00h ne correspondra plus à la 1ère position à gauche, 1ère ligne.

> 40 µ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

> 40 µs

Cursor or display shift

0

0

0

0

0

1

S/C

R/L

-

-

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

> 40 µs

Function set

0

0

0

0

1

DL

N

F

-

-

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

> 40 µs

Set CGRAM address

0

0

0

1

ACG5

ACG4

ACG3

ACG2

ACG1

ACG0

Positionne le compteur d'adresse de la CGRAM à la valeur (ACG5 ... ACG0)

> 40 µs

Set DDRAM address

0

0

1

ADD6

ADD5

ADD4

ADD3

ADD2

ADD1

ADD0

Positionne le compteur d'adresse de la DDRAM (ADD5 ... ADD0)

> 40 µs

Read busy & address

0

1

BF

AC6

AC5

AC4

AC3

AC2

AC1

AC0

Lit le drapeau BF (Busy Flag) et le compteur d'adresse (AC6 ... AC0)

BF = 1 → Le contrôleur est occupé et n’accepte aucune nouvelle instruction
BF = 0 → Le contrôleur est disponible pour une nouvelle instruction

> 1 µ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 data to CGRAM or DDRAM

1

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

Initialisation

  1. Attendre au moins 15ms depuis le passage à +5V de Vcc,

  2. Envoyer l'instruction Function set avec la valeur 0011XXXX,

  3. Attendre au moins 4.1ms,

  4. Envoyer à nouveau l'instruction Function set avec la valeur 0011XXXX,

  5. Attendre au moins 100µs,

  6. Envoyer à nouveau l'instruction Function set avec la valeur 0011XXXX,

  7. Si on veut activer le mode 4 bits, envoyer les 4 bits de poids fort de l'instruction Function set avec la valeur 0010,

  8. Configuration du nombre de lignes et de la matrice, en envoyant l'Instruction Function set avec par exemple la valeur 00111000 (8 bits, 2 lignes, 5x8pixels),

  9. Configuration du contrôle d'affichage, en envoyant l'instruction Display on/off control avec par exemple la valeur 00001100 (Affichage visible, curseur visible, curseur fixe),

  10. Effacement de l'écran, en envoyant l'instruction Clear display, avec pour valeur 00000001,

  11. Configuration du curseur, en envoyant l'instruction Entry set mode, avec par exemple pour valeur 00000110 (déplacement du curseur vers la droite, pas de décalage du compteur d'adresse).

  12. Fin de l'initialisation, l'écran est prêt à recevoir les autres instructions permettant l'affichage.

Mémoire d’affichage DDRAM (Display Data RAM)

Il s’agit la mémoire où sont stockés les caractères affichés.

L’adresse du caractère correspond à sa position à l’écran.

Pour un écran à 1 ligne (80 caractères max) :

  • le premier caractère de gauche est à l'adresse 0x00,

  • le caractère à sa droite est à l'adresse 0x01,

  • le caractère suivant est à l'adresse 0x02,

  • et ainsi de suite...

@ 0x00

@ 0x01

@ 0x02

@ 0x03

..........

@ 0x4C

@ 0x4D

@ 0x4E

@ 0x4F

Pour un écran à 2 lignes (40 caractères max par ligne) :

  • la logique d'accès au caractères est la même que pour un écran 1 ligne,

  • le logique d'accès au caractères est la même que pour un écran 1 ligne sauf que l'adresse du premier caractère de gauche commence à 0x40.

@ 0x00

@ 0x01

@ 0x02

@ 0x03

..........

@ 0x24

@ 0x25

@ 0x26

@ 0x27

@ 0x40

@ 0x41

@ 0x42

@ 0x43

..........

@ 0x64

@ 0x65

@ 0x66

@ 0x67

Pour l’écran à 2 lignes de 40 caractères, si on écrit un caractère à l’adresse 27h, le curseur vient se placer automatiquement à l’adresse 40h.

Pour un écran plus petit (de 2 lignes de 16 caractères par exemple), bien qu’inutile, il est possible d’accéder aux adresses mémoires des caractères inexistants.

Mémoire du générateur de caractères CGRAM (Character Generator RAM)

Pour une matrice de caractères de 5x8, il y a 8 caractères personnalisables dans la CGROM, et seulement 4 lorsque la matrice est de 5x11. Pour une matrice de 5x8 :

  • Le 1er caractère est accessible aux adresses 00h et 08h (de la DDRAM),

  • Le 2ème caractère est accessible aux adresses 01h et 09h,

  • Le 8ème caractère est accessible aux adresses 07h et 0Fh.

Pour configurer les caractères personnalisables :

  • il faut appeler la fonction « Set CGRAM address » où les bits « ACG5 ACG4 ACG3 » correspondent à l’adresse du caractère (ex : « 010 » pour le 3ème caractère) et les bits « ACG2 ACG1 ACG0 » à la ligne dans la matrice du caractère (ex : « 011 » pour la 3ème ligne en partant du haut),

  • il faut ensuite appeler la fonction « Write data to CGRAM » où les bits « D7 D6 D5 » sont mis à 0 et les bits « D4 D3 D2 D1 D0 » correspondent à l’état des pixels (0 = éteint, 1 = allumé).

Pour une matrice de 5x11 , même principe sauf que :

  • Le 1er caractère est accessible aux adresses 00h et 08h (de la DDRAM) pour les 8 lignes du haut, et 01h et 09h pour les 3 autres lignes,

  • Le 2ème caractère est accessible aux adresses 02h et 0Ah pour les 8 lignes du haut, ainsi que 03h et 0Bh pour les 3 autres lignes,

  • Le 4ème caractère est accessible aux adresses 06h et 0Eh pour les 8 lignes du haut, ainsi que 07h et 0Fh pour les 3 autres lignes.

Les jeux de caractères standards de la CGROM (Character Generator ROM)

Les 128 premiers caractères sont répartis comme suit :

  • les 16 premiers caractères correspondent aux caractères personnalisés stockés en CGRAM,

  • les 16 suivants sont des caractères de contrôle (flèches, guillemets, ...),

  • les 96 suivants sont à peu près les caractères ASCII.

Jeu de caractères du HD44780

Pour les 128 derniers caractères, il existe plusieurs standards en fonction de la référence du contrôleur « HD44780Uxxx » où « xxx » est le ROM code :

  • Si le « ROM code = A00 », alors le contrôleur utilise le jeu de caractère japonais,

  • Si le « ROM code = A02 », alors le contrôleur utilise le jeu de caractère européen.

Il peut exister encore d'autres jeux de caractères notamment pour les clones KS0070B et SPLC780A1.

Il faut se référer à la datasheet pour connaître la signification exacte de chaque emplacement de la CGROM, ou alors le vérifier expérimentalement.

Liens et documents externes



Le cycle d'écriture
 

On considère que la broche RW de l'afficheur est à l'état 0, on est donc toujours en mode écriture vers l'afficheur.
Les commandes envoyées vers l'afficheur peuvent se décomposer en deux groupes qui sont
l'écriture d'une instruction ( effacement de l'afficheur par exemple ),
l'écriture d'une donnée ( affichage d'un caractère sur l'écran ).

Écriture d'une instruction

La broche RS doit être à l'état 0.
On présente le code de l'instruction sur 8 bits (D0 à D7).
On envoie une impulsion sur la broche E. 
L'instruction est prise en compte sur le front descendant de cette impulsion.
L'instruction peut être présentée avant le front montant de l'impulsion.

Écriture d'une donnée

La broche RS doit être à l'état 1.
On présente le code de la donnéesur 8 bits (D0 à D7).
On envoie une impulsion sur la broche E. 
La donnée est prise en compte sur le front descendant de cette impulsion.
La donnée peut être présentée avant le front montant de l'impulsion.





Voici le code sur un Atmega8 en assembleur :

;=========================================================================

; Programme pour piloter un écran LCD 1602 (HD44780) sur un ATmega8

;=========================================================================

; pour ATMEGA8

; Créé le : 26/04/2013

; Dernière mise a jour: 26/04/2013

; Auteur: Uriel

;=======================================================================

; Fréquence : par défaut, l'Atmega8 fonctionne en 1mhz interne.

; Pour passer en 8mhz interne, mettre les fusibles de avrdude "Low Fuse : C4" et "High Fuse : D9" (attention, il démarre tout de suite)

; Pour 16mhz externe : lf:DF et hf:D9 (démarrage immédiat). Le quartz est entre PB6 et PB7 et les condenssateurs (entre 12 et 22pF inclus) sont reliés de ces pattes au 0V.


;======================

; Entrées/Sorties :

;======================

; Entrée :

; PB3 : Entrée bouton poussoir "Gauche"

; PB2 : Entrée bouton poussoir "Milieu"

; PB1 : Entrée bouton poussoir "Droite"

; Sorties :

; PD0 : Borne 4 "RS"

; PD1 : Borne 5 "R/W"

; PD2 : Borne 6 "E"

; PD3 : Borne 7 "D0"

; PD4 : Borne 8 "D1"

; PB6 : Borne 9 "D2"

; PB7 : Borne 10 "D3"

; PD5 : Borne 11 "D4"

; PD6 : Borne 12 "D5"

; PD7 : Borne 13 "D6"

; PB0 : Borne 14 "D7"


.include "m8def.inc" ; Nom du fichiers de références des registres (ATMEGA 8)

;------------------------------------------------------------------------

; Déclaration des Variables

;------------------------------------------------------------------------

.def variable1 = R1 ; Il y a 32 registres de 16 bits adressés de r0 à r31 avec de r16 à r31 pour travailler en valeur immédiates

.def variable2 = R2

.def a=R16

.def b=R17

.def c=R18

.def d=R19

.def variablepwm=R20



.DSEG ; Début de zone de la partie "taille"

nombre1: .BYTE 1 ; Nombre codé sur 1 octet en binaire

nombre2: .BYTE 3 ; Nombre codé sur 3 octets en binaire

dividende: .BYTE 3

numerateur: .BYTE 1

denominateur: .BYTE 1


;------------------------------------------------------------------------

; Constantes

.equ constante1 = 0b00000001 ; On met la constante à 1

;------------------------------------------------------------------------

;Déclaration des Vecteurs d'interruptions

;------------------------------------------------------------------------

.CSEG ; Début de la partie "données"

.ORG 0x0000 ; Début de la zone memoire programme

rjmp RESET ; RESET

rjmp EXT_INT0 ; Interruption externe INT0

rjmp EXT_INT1 ; Interruption externe INT1

rjmp TIM2_COMP ; Interruption comparaison reussie TIMER2

rjmp TIM2_OVF ; Interruption debordement compteur TIMER2

rjmp TIM1_CAPT ; Interruption entree capture TIMER1

rjmp TIM1_COMPA ; Interruption comparateurA TIMER1

rjmp TIM1_COMPB ; Interruption comparateurB TIMER1

rjmp TIM1_OVF ; Interruption debordement compteur TIMER1

rjmp TIM0_OVF ; Interruption debordement compteur TIMER0

rjmp SPI_STC ; Interruption transmissions SPI terminee

rjmp UART_RXC ; Interruption reception UART termine RX

rjmp UART_DRE ; Interruption UART vide

rjmp UART_TXC ; Interruption emission UART termine TX

rjmp ADC_ok ; Interruption Conversion A/D terminee

rjmp EE_RDY ; Interruption EEPROM prete

rjmp ANA_COMP ; Interruption comparaison analogique effectuee

;------------------------------------------------------------------------

; Routines de traitement des interruptions

;------------------------------------------------------------------------

EXT_INT0: ; Déclenchée par les signaux de BEMF sur PD2 en front montant et descendant

; Tâche à effectuer

reti ; Retour après l'interruption


;------------------------------------------------------------------------

EXT_INT1: reti

;------------------------------------------------------------------------

TIM2_COMP:reti

;------------------------------------------------------------------------

TIM2_OVF: reti

;------------------------------------------------------------------------

TIM1_CAPT:reti

;------------------------------------------------------------------------

TIM1_COMPA:reti

;------------------------------------------------------------------------

TIM1_COMPB:reti

;------------------------------------------------------------------------

TIM1_OVF: reti

;------------------------------------------------------------------------

TIM0_OVF: reti

;------------------------------------------------------------------------

SPI_STC: reti

;------------------------------------------------------------------------

UART_RXC: reti

;------------------------------------------------------------------------

UART_DRE: reti

;------------------------------------------------------------------------

EE_RDY: reti

;------------------------------------------------------------------------

ANA_COMP: reti

;------------------------------------------------------------------------

ADC_ok: reti

;------------------------------------------------------------------------

UART_TXC: reti

;------------------------------------------------------------------------

UART_RXC1:reti

;------------------------------------------------------------------------

;Programme de RESET

cli ; Désactive les vecteurs d'interruptions pendant la séquence

RESET:

ldi R16,low(RAMEND) ; Charge le BYTE faible de fin de RAM dans le registre R16

out SPL,R16 ; Initialisation de la pile a l'adresse haute de la RAM

ldi R16,high(RAMEND) ; Charge le BYTE fort de fin de RAM dans le registre R16

out SPH,R16 ; Initialisation du BYTE fort de la pile à l'adresse haute de la RAM

CLI ; Désactive les vecteurs d'interruptions pendant la séquence

;------------------------------------------------------------------------

; Initialisation des ports

; PORT B:

ldi a,0b11110001 ; PORTB en entrée (0=Entrée, 1=Sortie)

out ddrb,a ; On écrit dans le PORTB

; PORT C:

ldi a,0b00000000 ; Toutes en entrées (0=Entrée, 1=Sortie)

out ddrc,a


; PORT D:

ldi a,0b11111111 ; PORTD en sortie (0=Entrée, 1=Sortie)

out ddrd,a


CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0


;------------------------------------------------------------------------

;TCCR0

; Définit le mode de fonctionnement du Timer0


ldi a,0b00000001 ; bits7a3 = non utilise bits2,1,0 = taux de prédivision de l'horloge pour 001, on fonctionne à la fréquence de l'horloge

out TCCR0,a


;------------------------------------------------------------------------

;PROGRAMME PRINCIPAL

;------------------------------------------------------------------------

; Initialisation

RCALL temporisation3 ; On commence par attendre 200mS pendant l'initialisation de l'afficheur

; Il faut que la tension soit stabilisée... donc avec mon alimentation, je dois mettre une longue tempo...

; Premier envois

SBI PORTD,6 ; On met D5 à 1

SBI PORTD,5 ; On met D4 à 1 : interface 8 BITS (si "0" alors 4 BITS)

RCALL validation ; On valide les données envoyées au LCD

RCALL temporisation ; On attend 16mS avant d'envoyer la suite

; Deuxième envois

RCALL validation ; On valide les données envoyées au LCD

RCALL temporisation ; On fait une pause de 16mS

; Troisième envois

RCALL validation ; On valide les données envoyées au LCD

RCALL temporisation1 ; On fait une pause de 16mS

CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0


; Function set

SBI PORTD,6 ; On met D5 à 1

SBI PORTD,5 ; On met D4 à 1 : interface 8 BITS (si "0" alors 4 BITS)

SBI PORTB,7 ; On met D3 à 1 : Deux lignes d'affichage (si "0" alors 1 ligne)

SBI PORTB,6 ; On met D2 à 1 : Matrice 5 x 11 points (si "0" alors 5 x 8)

RCALL validation ; On valide les données envoyées au LCD

CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0


; Clear display : efface l'écran et retourne dans la case en haut à gauche

SBI PORTD,3 ; On met D0 à 1

RCALL validation ; On valide les données envoyées au LCD

RCALL temporisation1 ; On fait une pause de 1mS

RCALL temporisation1 ; On fait une pause de 1mS

CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0


; Entry set mode

SBI PORTB,6 ; On met D2 à 1

SBI PORTD,4 ; On met D1 à 1 : déplacement du curseur à droite (0=Gauche)

CBI PORTD,3 ; On met D0 à 0 : L'affichage n'est pas décalé (1 = l'affichage se décale avec le curseur)

RCALL validation ; On valide les données envoyées au LCD

CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0


; Display on/off control

SBI PORTB,7 ; On met D3 à 1

SBI PORTB,6 ; On met D2 à 1 : affichage visible (0 = Invisible)

CBI PORTD,4 ; On met D1 à 0 : curseur invisible (1 = Visible)

CBI PORTD,3 ; On met D0 à 0 : curseur fixe (1 = Clignotant)

RCALL validation ; On valide les données envoyées au LCD

CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0


;------------------------------------------------------------------------

;Progamme principal, ici, on affiche du texte

SEI ; On permet les interruptions


programme: ; Routine qui écrit du texte

; Il faut laisser RS à 1 pendant toute la séquence d'envois

RCALL temporisation2 ; On attend 50µS pour que RS précède le signal


; Ecrit "C"

LDI a,0b10011001

OUT PORTD,a ; On met D6, D1,D0 et RS à 1

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "o"

LDI a,0b11011001

OUT PORTD,a ; On met D6, D5, D1, D0 et RS à 1

LDI a,0b11000000

OUT PORTB,a ; On met D3, D2 à 1

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "u"

LDI a,0b11101001

OUT PORTD,a ; On met D6, D5, D4, D0 et RS à 1

LDI a,0b01000000

OUT PORTB,a ; On met D2 à 1

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "c"

LDI a,0b11011001

OUT PORTD,a ; On met D6, D5, D1,D0 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "o"

LDI a,0b11011001

OUT PORTD,a ; On met D6, D5, D1, D0 et RS à 1

LDI a,0b11000000

OUT PORTB,a ; On met D3, D2 à 1

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "u"

LDI a,0b11101001

OUT PORTD,a ; On met D6, D5, D4, D0 et RS à 1

LDI a,0b01000000

OUT PORTB,a ; On met D2 à 1

RCALL validation ; On valide les données envoyées au LCD


; Ecrit " " "Espace"

LDI a,0b01000001

OUT PORTD,a ; On met D5 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "P"

LDI a,0b10100001

OUT PORTD,a ; On met D6, D4 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "a"

LDI a,0b11001001

OUT PORTD,a ; On met D6, D5, D0 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "p"

LDI a,0b11100001

OUT PORTD,a ; On met D6, D5, D4 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "a"

LDI a,0b11001001

OUT PORTD,a ; On met D6, D5, D0 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit " " "Espace"

LDI a,0b01000001

OUT PORTD,a ; On met D5 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


; Ecrit "!"

LDI a,0b01001001

OUT PORTD,a ; On met D5, D0 et RS à 1

LDI a,0b00000000

OUT PORTB,a ; On efface le port B

RCALL validation ; On valide les données envoyées au LCD


fin:

RJMP fin


; Return home

SBI PORTD,4 ; On met D1 à 1 : Place le curseur dans la position d'origine en haut à gauche

SBI PORTD,3 ; On met D0 à 1

RCALL temporisation2 ; On attend 50µS

CBI PORTD,2 ; On met E à 0 : Valide les entrées sur front descendant de cette impulsion

RCALL temporisation2 ; On attend 50µS

RCALL temporisation1 ; On fait une pause de 1mS

RCALL temporisation1 ; On fait une pause de 1mS

CBI PORTD,4 ; On met D1 à 0

CLR a

OUT PORTD,a ; On met le PORT D à 0

OUT PORTB,a ; On met le PORT B à 0

RCALL temporisation1 ; On fait une pause de 1mS


;------------------------------- Validation -------------------------------------------

validation: ; Routine qui valide les données

SBI PORTD,2 ; On met E à 1

; On effectue 100µS de temporisation

ldi d,80

soustempov1:

NOP ; Aucune opération : sert à ajuster la durée

NOP

NOP

NOP

NOP

NOP

NOP

dec d ; On décrémente

brne soustempov1 ; Si différent de "Z", on va à la routine indiqué (il faut que R31 et R30 soient à zéro)


CBI PORTD,2 ; On met E à 0 : Valide les entrées sur front descendant de cette impulsion


; On effectue 100µS de temporisation

ldi d,80

soustempov2:

NOP ; Aucune opération : sert à ajuster la durée

NOP

NOP

NOP

NOP

NOP

NOP

dec d ; On décrémente

brne soustempov2 ; Si différent de "Z", on va à la routine indiqué (il faut que R31 et R30 soient à zéro)


RET ; On retourne au "rcall" précédent



;------------------------------------- Temporisation ---------------------------------------

temporisation: ; Routine qui retarde le programme de 16mS à 8Mhz avec 7 NOP, et 1x50x255


ldi b,1 ; On met la valeur dans la variable

soustempo1:

ldi c,50

soustempo2:

ldi d,255

soustempo3:

NOP ; Aucune opération : sert à ajuster la durée

NOP

NOP

NOP

NOP

NOP

NOP

dec d ; On décrémente

brne soustempo3 ; Si différent de "Z", on va à la routine indiqué (il faut que R31 et R30 soient à zéro)

dec c

brne soustempo2 ; IDEM : multiple 2

dec b

brne soustempo1 ; IDEM : multiple 3


RET ; On retourne au "rcall" précédent


;------------------------------------- Temporisation N°1 ---------------------------------------

temporisation1: ; Routine qui retarde le programme de 1mS à 8Mhz avec 7 NOP, et 1x4x200


ldi b,1 ; On met la valeur dans la variable

soustempo11:

ldi c,4

soustempo12:

ldi d,200

soustempo13:

NOP ; Aucune opération : sert à ajuster la durée

NOP

NOP

NOP

NOP

NOP

NOP

dec d ; On décrémente

brne soustempo13 ; Si différent de "Z", on va à la routine indiqué (il faut que R31 et R30 soient à zéro)

dec c

brne soustempo12 ; IDEM : multiple 2

dec b

brne soustempo11 ; IDEM : multiple 3


RET ; On retourne au "rcall" précédent


;------------------------------------- Temporisation N°2 ---------------------------------------

temporisation2: ; Routine qui retarde le programme de 100µS à 8Mhz avec 7 NOP, et 1x1x80


ldi b,1 ; On met la valeur dans la variable

soustempo21:

ldi c,1

soustempo22:

ldi d,80

soustempo23:

NOP ; Aucune opération : sert à ajuster la durée

NOP

NOP

NOP

NOP

NOP

NOP

dec d ; On décrémente

brne soustempo23 ; Si différent de "Z", on va à la routine indiqué (il faut que R31 et R30 soient à zéro)

dec c

brne soustempo22 ; IDEM : multiple 2

dec b

brne soustempo21 ; IDEM : multiple 3


RET ; On retourne au "rcall" précédent


;------------------------------------- Temporisation N°3 ---------------------------------------

temporisation3: ; Routine qui retarde le programme de 200mS à 8Mhz avec 7 NOP, et 3x210x255


ldi b,3 ; On met la valeur dans la variable

soustempo31:

ldi c,210

soustempo32:

ldi d,255

soustempo33:

NOP ; Aucune opération : sert à ajuster la durée

NOP

NOP

NOP

NOP

NOP

NOP

dec d ; On décrémente

brne soustempo33 ; Si différent de "Z", on va à la routine indiqué (il faut que R31 et R30 soient à zéro)

dec c

brne soustempo32 ; IDEM : multiple 2

dec b

brne soustempo31 ; IDEM : multiple 3


RET ; On retourne au "rcall" précédent


;------------------------------------------------------------------------

;ROUTINES

;------------------------------------------------------------------------

portc_entier:


ldi a,0b00000001

out portc,a ; On assigne chaque patte du port à 1 ou 0

ret


patte_portc_sortie:

CBI portc,3 ; On met la patte à 0

SBI portc,3 ; On met la patte à 1


test_entree:

SBIS pind,7 ; On saute si le BIT est à 1

ret


;----------------------------------------------------------------------

; Compteur : on utilise le TMR0 qui possède 8 bits donc 256 valeurs.

Compteur: ; Tous les 256 cycles d'horloge, il déborde, exécutant la routine TIM0_OVF:

LDI R16,0b00000001 ; Prescaler à 0 (trois derniers bits déterminent la prédivision)

OUT TCCR0,R16

LDI R16,0B00000001 ; Activation avec autorisation d'interruption et de débordement

OUT TIMSK,R16

LDI R16,0B0000000 ; Compteur à 0

OUT TCNT0,R16

SEI ; Global Interrupt Enable

RET





15

Avec un Arduino :

C'est déjà beaucoup plus simple ^^
Il suffit de suivre ce shéma :

Et d'envoyer le code suivant (par exemple) :

/*
LiquidCrystal Library - par Uriel

The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)

Code inspiré de l'original :
http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/

// include the library code:
#include
// Pattes utilisées
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
// Définit le nombre de caractères et de lignes
lcd.begin(16, 2);
// Affiche le texte à l'écran
lcd.print("Bonjour Uriel !");
}

void loop() {
// Met le curseur à la colone 0 ligne 1 (ligne du bas)
lcd.setCursor(0, 1);
// Affiche le nombre de secondes depuis la mise sous tensions
lcd.print((millis()/1000));
}

Avec un module I2C :

08/04/2014
Petit module qui sert à diminuer le nombre de fils à câbler : quatre seulement, en utilisant le protocole de communication : I²C (SDA SCL).
Il se soude dirrectement sur les broches de l'écran LCD1602.
ça vaut dans les 1€ livré.

La librairie qui convient avec ma versions Arduino 1.0.5 est ici.

Le code :


/*
Programme type d'utilisation du module LCD sur un écran 1602
Créé le 08/04/2014
*/

#include
#include // Difficultés fréquentes avec les librairies et les versions...

LiquidCrystal_I2C lcd(0x27,16,2); // Met à adresse 0x27 du LCD le type : 16 charactères sur 2 lignes

void setup()
{
lcd.init(); // Initialisation du LCD

lcd.backlight(); // Allume la diode de rétro-éclairage
lcd.print("Salut Uriel !"); // Affiche le message entre guillemets.
}

void loop()
{
lcd.setCursor(0, 1); // Met le curseur à la colone 0 ligne 1 (ligne du bas)
lcd.print((millis()/1000)); // Affiche le nombre de secondes écoulées
}

Création le 18/08/2014
Dernière mise à jour :18/08/2014 par Uriel