Changes between Version 2 and Version 3 of IOC21_T02


Ignore:
Timestamp:
Feb 1, 2022, 4:53:35 PM (2 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • IOC21_T02

    v2 v3  
    336336
    337337
     338= Pilotage d'un écran LCD en mode utilisateur et par un driver =
     339
     340
     341L'objectifs est de comprendre le fonctionnement d'un écran LCD et ses fonctions de base
     342
     343Ressources:
     344* newhaven display est le fabriquant du module LCD, c'est donc, en principe la référence.
     345  * Dans ce document ([[http://www.newhavendisplay.com/specs/NHD-0420DZ-FL-YBW.pdf | Datasheet du LCD du module]]), il est dit que le contrôleur du LCD est le ST7066U, mais, sauf preuve du contraire, la séquence
     346    d'initialisation du LCD décrite dans la documentation du [[http://www.newhavendisplay.com/app_notes/ST7066U.pdf | ST7006U]]
     347    ne fonctionne pas...
     348* HD44780 est le contrôleur historique de la majorité des LCD de ce genre. La procédure d'initialisation fonctionne.
     349  * [[http://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller | LCD Display HD44780]]
     350    [[https://www.sparkfun.com/datasheets/LCD/HD44780.pdf | Datasheet du HD44780]]
     351* Le document suivant définit comment est adressé la mémoire "vidéo" du LCD.
     352  * [[http://web.alfredstate.edu/faculty/weimandn/lcd/lcd_addressing/lcd_addressing_index.html | Adressage de la mémoire interne de l'afficheur]]
     353
     354Prenez le temps de parcourir les documents sur les afficheurs avant de commencer à programmer.
     355
     356Le code à modifier se trouve en pièces jointes de cette page [htdocs:docs/lcd/lcd_user.c lcd_user.c] et [htdocs:docs/lcd/Makefile Makefile]. Vous pourrez les copier dans un répertoire `lcd_user`
     357
     358== 1. Configuration des GPIO pour le pilotage de l'écran ==
     359
     360L'écran LCD de type HD44780 dispose de plusieurs signaux de contrôle et de données. Les signaux de contrôle sont au nombre de 3: RS, RW et E. Les signaux de données sont au nombre de 4 ou 8 suivant le mode.
     361
     362Dans ce TP, nous utiliserons l'écran en mode 4-bit car la carte Raspberry Pi dispose d'un nombre limité de GPIO. De plus, le signal RW sera connecté directement à 0V (donc toujours en écriture) car nous n'allons gérer que les opérations d'écriture (Note: les GPIO de la carte Raspberry Pi fonctionnent en 3.3V, ils ne supportent pas les niveaux de tension 5V émis par l'afficheur, demandez-moi cela n'est pas clair).
     363
     364Les signaux de contrôle RS et E sont utilisés de la manière suivante:
     365* RS vaut 1 pour l'envoi d'une donnée (e.g. un caractère) et vaut 0 pour l'envoi d'une commande (instruction).
     366* E est un signal de validation; la valeur sur le bus de données (4 bits) est pris en compte à chaque front descendant de ce signal.
     367
     368Voici le mapping des GPIO pour les différents signaux:
     369
     370||=   Signal LCD  =||=     GPIO     =||
     371||       RS        ||       7        ||
     372||       E         ||       27       ||
     373|| D4, D5, D6, D7  || 22, 23, 24, 25 ||
     374
     375Dans la documentation de l'afficheur, on peut savoir :
     376* Comment faut-il configurer les GPIOs pour les différents signaux de l'afficheur LCD ?
     377* Comment écrire des valeurs vers le LCD ?
     378* Quelles valeurs doivent être envoyées vers l'afficheur pour réaliser l'initialisation ?
     379* Comment demander l'affichage d'un caractère ?
     380* Comment envoyer des commandes telles que : l'effacement de l'écran, le déplacement du curseur, etc. ?
     381
     382En particulier, page 11 de la documentation ([[http://www.newhavendisplay.com/specs/NHD-0420DZ-FL-YBW.pdf | Datasheet du LCD de la plateforme]]) se trouve du pseudo-code pour l'usage de l'afficheur.
     383* P1 est un registre dont l'état est recopié sur les broches D0 à D7 (bit7 de P1 sur D7, bit6 sur D6, etc. jusqu'à D4).
     384* D_I est un registre dont l'état est recopié sur RS qui indique si on envoie un caractère (D) ou une instruction (I).
     385* R_W est un registre dont l'état est recopié sur RW
     386* Delay() est une attente en microsecondes.
     387
     388{{{#!c
     3894-bit Initialization:
     390/**********************************************************/
     391void command(char i)
     392{
     393  P1 = i;                       //put data on output Port
     394  D_I =0;                       //D/I=LOW : send instruction
     395  R_W =0;                       //R/W=LOW : Write       
     396  Nybble();                     //Send lower 4 bits
     397  i = i<<4;                     //Shift over by 4 bits
     398  P1 = i;                       //put data on output Port
     399  Nybble();                     //Send upper 4 bits
     400}
     401/**********************************************************/
     402void write(char i)
     403{
     404  P1 = i;                       //put data on output Port
     405  D_I =1;                       //D/I=HIGH : send data
     406  R_W =0;                       //R/W=LOW : Write   
     407  Nybble();                     //Clock lower 4 bits
     408  i = i<<4;                     //Shift over by 4 bits
     409  P1 = i;                       //put data on output Port
     410  Nybble();                     //Clock upper 4 bits
     411}
     412/**********************************************************/
     413void Nybble()
     414{
     415  E = 1;
     416  Delay(1);                     //enable pulse width  >= 300ns
     417  E = 0;                        //Clock enable: falling edge
     418}
     419/**********************************************************/
     420void init()
     421{
     422  P1 = 0;
     423  P3 = 0;
     424  Delay(100);                   //Wait >40 msec after power is applied
     425  P1 = 0x30;                    //put 0x30 on the output port
     426  Delay(30);                    //must wait 5ms, busy flag not available
     427  Nybble();                     //command 0x30 = Wake up 
     428  Delay(10);                    //must wait 160us, busy flag not available
     429  Nybble();                     //command 0x30 = Wake up #2
     430  Delay(10);                    //must wait 160us, busy flag not available
     431  Nybble();                     //command 0x30 = Wake up #3
     432  Delay(10);                    //can check busy flag now instead of delay
     433  P1= 0x20;                     //put 0x20 on the output port
     434  Nybble();                     //Function set: 4-bit interface
     435  command(0x28);                //Function set: 4-bit/2-line
     436  command(0x10);                //Set cursor
     437  command(0x0F);                //Display ON; Blinking cursor
     438  command(0x06);                //Entry Mode set
     439}
     440/**********************************************************/
     441}}}
     442
     443== 2. Fonctionnement de l'écran et fonctions de base ==
     444
     445La prise en compte de la donnée est réalisée lors d'un front descendant du signal E.
     446Pour créer un front descendant:
     447* on place la donnée,
     448* puis le signal E est mis à 1 pendant 1µs.
     449
     450[[Image(htdocs:png/command_lcd.png, width=900px, nolink)]]
     451
     452Nous utilisons l'afficheur LCD en mode 4 bits. Or, les commandes et les données sont transmises sur 8 bits ou 1 octet. Ainsi, toutes les commandes et toutes les données sont transmises en deux étapes: les 4 bits de poids fort et ensuite les 4 bits de poids faible.
     453
     454Nous avons toutes les fonctions dont nous avons besoin. Maintenant regardons d'un peu plus près la phase d'initialisation de l'afficheur LCD. Au démarrage, l'afficheur est dans un mode non défini (8 bits ou 4 bits). Il faut donc le forcer en mode 4 bits.
     455
     456Vous êtes prêt à tester votre code et vérifier qu'il affiche correctement une chaine de caractère.
     457erry Pi.
     458
     459Il peut être utile de manipuler la position du curseur pour choisir où placer les caractères sur l'afficheur.
     460
     461Pour cela, l'afficheur dispose de trois instructions: Cursor home, Display clear et Set DDRAM address. La dernière instruction est relative à la mémoire interne de l'afficheur (Display Data RAM).
     462
     463La mémoire DDRAM est construite de la manière suivante:
     464||0x00 ..... Ligne 1 ..... 0x13||
     465||0x40 ..... Ligne 2 ..... 0x53||
     466||0x14 ..... Ligne 3 ..... 0x27||
     467||0x54 ..... Ligne 4 ..... 0x67||
     468
     469On souhaites utiliser toutes les lignes
     470
     471|| **Questions:**\\1. Répondez aux questions qui se trouve dans le code [htdocs:docs/lcd/lcd_user.c lcd_user.c] \\2. Ecrire une fonction lcd_set_cursor qui positionne le curseur aux coordonnées (x,y) avec x la colonne, y la ligne.\\3. Ecrire un programme qui affiche la chaine passée en paramètre sur chacune des lignes de l'afficheur.
     472[[BR]]
     473
     474
     475
     476
     477
    338478=== Création du driver qui accède aux GPIO
    339479