Comment utiliser un écran LCD ?

NIVEAU 2 / SPI

Objectifs

  • Câbler un écran LCD de type EA DOG 163 en SPI
  • Utiliser l’écran pour afficher des informations

Pré-requis

Ecran LCD / SPI

On se propose ici d’utiliser un écran LCD, de type EA DOG M163 5V, équipé d’une liaison SPI. La documentation technique de cet écran est disponible ici.

Connexion de l’écran à la carte Nucléo

Une carte d’extension constituée d’un écran LCD EA DOG 163 possédant 3 lignes de 16 caractères a été réalisée pour simplifier la connectivité entre la carte Nucléo et l’écran. Le câblage est le suivant :

Les broches SCK, SDO et CS_LCD sont les broches standard du protocole SPI, vue du microcontroleur (voir tutoriel Configurer un réseau point à point SPI). L’écran LCD étant en écriture seule, la broche SDI n’existe pas.

Cependant, ce module permettant de gérer à la fois les caractères à afficher et le mode d’affichage, une broche supplémentaire, nommée RS_LCD, est présente pour spécifier s’il s’agit d’un caractère ou d’une commande à transmettre. Elle doit être reliée à une sortie du microcontroleur.

Attention ! L’écran doit être alimenté avec une tension de 5V.

Initialisation du module SPI

Pour pouvoir utiliser l’écran LCD, il faut dans un premier temps initialiser la liaison SPI les reliant. Pour cela, on peut utiliser le code suivant :

SPI spi(D11,D12,D13); // mosi, miso, sck
DigitalOut CS_LCD(D8);

Ce composant a en plus besoin d’un signal nommé RS_LCD :

DigitalOut RS_LCD(D9);

Pour ensuite paramètrer la liaison SPI, il faudra écrire dans la fonction main :

spi.format(8,0);
spi.frequency(100000);

Initialisation du composant

Pour paramétrer la plupart des composants numériques, il est nécessaire de suivre une procédure d’initialisation propre à chacun d’entre eux. Dans le cas de cet écran LCD, on trouve dans la documentation technique diverses commandes que l’on peut utiliser pour contrôler l’affichage à l’écran. En particulier, on retrouve cette procédure d’initialisation :

On peut alors écrire la fonction d’initialisation suivante :

void LCD_DOG_init(void){
    CS_LCD = 0;
    RS_LCD = 0;
    spi.write(0x29); // Function Set - Table 1
    spi.write(0x1D); // Bias Set
    spi.write(0x50); // Power Control
    spi.write(0x6C); // Follower Control
    spi.write(0x78); // Contrast Set
    spi.write(0x03); // Function Set - Table 0
    spi.write(0x0F); // Display On
    spi.write(0x01); // Clear Display
    wait_ms(2);
    spi.write(0x06); // Cursor On
    wait_ms(10);
    RS_LCD=1;
    CS_LCD=1;
    wait_ms(10);
}

Dans cette fonction, on fait passer les signaux CS_LCD et RS_LCD à ‘0’, pour démarrer la discussion en mode envoi de commande à l’écran LCD. Puis on écrit la suite de commandes nécessaires à l’initialisation, par le biais de la fonction write(char val) de la classe SPI. La commande permettant d’effacer l’écran LCD est plus longue que les autres, on laisse alors 2 ms après celle-ci avant de renvoyer la commande d’allumage de l’écran.

Pour définir la fin de la transmission, on repasse à ‘1’ les signaux CS_LCD et RS_LCD.

Ecriture d’un caractère

Une fois l’initialisation écrite, il ne reste qu’à écrire sur le LCD.
Cela se fait caractère par caractère à l’aide de la même fonction write(char val), il suffit simplement de donner un élément de type char en paramètre.

Pour envoyer le caractère ‘a’ sur l’afficheur, il faut alors écrire :

CS_LCD = 0;
spi.write('a'); 
CS_LCD=1;

Bibliothèque de fonctions

Une bibliothèque est disponible à l’adresse suivante : https://os.mbed.com/users/villemejane/code/EADogLcd/

Afin de simplifier l’utilisation de l’écran, il peut être intéressant d’écrire quelques fonctions de base. En particulier, il peut être intéressant (en plus de la fonction d’initialisation du composant comme vu précédemment) d’avoir des fonctions qui permettent :

  • d’afficher un caractère à l’écran – void LCD_DOG_writeChar(char val)
  • de déplacer le curseur à une position donnée – void LCD_DOG_setPosition(char ligne, char colonne)
  • d’écrire une chaîne de caractères sur une ligne de l’écran – void LCD_DOG_writeStr(char *c, char ligne, char colonne)
  • d’effacer l’écran – void LCD_DOG_clear(void)

Ecriture d’un caractère à l’écran

Pour afficher un caractère à l’écran, à la position du curseur, il suffit de reprendre les lignes vues précédemment :

void LCD_DOG_writeChar(char val){
	CS_LCD = 0;
	spi.write(val); 
	CS_LCD=1;
}

On peut alors l’utiliser par la suite de la façon suivante, pour écrire le caractère ‘z’ :

LCD_DOG_writeChar('z');

Déplacer le curseur

Pour déplacer le curseur à un endroit souhaité de l’écran, on peut utiliser la commande Set DDRAM Adress (présentée dans la documentation technique). L’écran LCD peut être vu comme un tableau linéaire de 3 x 16 octets (dont la première case commence par l’adresse 0). La première ligne est stockée dans les cases d’adresses 0 à 15, la seconde ligne est stockée dans les cases d’adresses 16 à 31…

Ainsi pour accèder à la 4ème case de la 2ème ligne, il faut aller à la case d’adresse : \((2-1) \cdot 16 + (4-1)\).

Le code correspondant est alors :

void LCD_DOG_setPosition(char ligne, char colonne){
	char adress = 0x80 + ((ligne - 1) * 16) + (colonne - 1);
	CS_LCD = 0;
	RS_LCD = 0;
	spi.write(adress); 
	CS_LCD=1;
	RS_LCD = 1;
}

On peut alors l’utiliser par la suite de la façon suivante, pour placer le curseur à la 2ème ligne et 4ème colonne :

LCD_DOG_setPosition(2, 4);

Ecrire une chaîne de caractères

Tout comme en C standard, les chaînes de caractères sont des tableaux finis de caractères. Le symbole ‘\0’ existe également et permet de délimiter la fin de chaîne de caractères.

Pour pouvoir afficher une chaine de caractère à un endroit particulier de l’écran, on peut alors réaliser une fonction de la sorte :

void LCD_DOG_writeStr(char *c, char ligne, char colonne){
    char i = 0;
    LCD_DOG_setPosition(ligne,colonne);
    while(c[i] != '\0') {
        LCD_DOG_writeChar(c[i]);
        i++;
    }
}

Pour afficher le texte “Bonjour” contenu dans la chaîne de caractère test à la position 3ème ligne et 2ème colonne, il faudra faire :

char ch[10];
sprintf(ch, "Bonjour");
LCD_DOG_writeStr(ch, 3, 2);

Effacer l’écran

Pour effacer l’écran, il faut faire appel à la commande de l’écran Clear Display :

void LCD_DOG_clear(void){
    CS_LCD = 0;
    RS_LCD = 0;
    spi.write(0x01); //Clear Display
    wait_ms(2);         //delay 2 ms
    RS_LCD = 1;
    CS_LCD = 1;
}

Exemple complet

#include "mbed.h"

SPI spi(D11,D12,D13); // mosi, miso, sck
DigitalOut CS_LCD(D8);
DigitalOut RS_LCD(D9);



void LCD_DOG_writeChar(char val){
  CS_LCD = 0;
  spi.write(val); 
  CS_LCD=1;
}

void LCD_DOG_setPosition(char ligne, char colonne){
  char adress = 0x80 + ((ligne - 1) * 16) + (colonne - 1);
  CS_LCD = 0;
  RS_LCD = 0;
  spi.write(adress); 
  CS_LCD=1;
  RS_LCD = 1;
}

void LCD_DOG_writeStr(char *c, char ligne, char colonne){
    char i = 0;
    LCD_DOG_setPosition(ligne,colonne);
    while(c[i] != '\0') {
        LCD_DOG_writeChar(c[i]);
        i++;
    }
}

void LCD_DOG_clear(void){
    CS_LCD = 0;
    RS_LCD = 0;
    spi.write(0x01); //Clear Display
    wait_ms(2);         //delay 2 ms
    RS_LCD = 1;
    CS_LCD = 1;
}

void LCD_DOG_init(void){
    CS_LCD = 0;
    RS_LCD = 0;
    spi.write(0x29); // Function Set - Table 1
    spi.write(0x1D); // Bias Set
    spi.write(0x50); // Power Control
    spi.write(0x6C); // Follower Control
    spi.write(0x7C); // Contrast Set
    spi.write(0x03); // Function Set - Table 0
    spi.write(0x0F); // Display On
    spi.write(0x01); // Clear Display
    wait_ms(2);
    spi.write(0x06); // Cursor On
    wait_ms(10);
    RS_LCD=1;
    CS_LCD=1;
    wait_ms(10);
}

int main(void){
    int i;
    char ch[17];
    spi.format(8,0);
    spi.frequency(100000);
    RS_LCD = 1;
    CS_LCD = 1;
    LCD_DOG_init();
    while(1){
        i++;
        sprintf(ch, "I = %d ", i);
        LCD_DOG_writeStr(ch, 1, 1);
        wait(1.0);
        LCD_DOG_clear();
    }
}

Tutoriel lié

MInE Prototyper Prototyper avec Nucleo et MBED

Nucleo – Utiliser un écran LCD / 2