Changes between Initial Version and Version 1 of Peri19_T04


Ignore:
Timestamp:
Mar 8, 2019, 11:03:14 AM (5 years ago)
Author:
franck
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Peri19_T04

    v1 v1  
     1{{{#!comment
     2Ce TME a été créé par Julien Peeters et modifié par Franck Wajsbürt
     3
     4
     5= TP3 : Pilotage d'un écran LCD en mode utilisateur et par un driver =
     6
     7
     8Objectifs:
     9* Fonctionnement d'un écran LCD et fonctions de base
     10* Ecriture d'un driver d'affichage
     11* Usage de IOCTL
     12* Affichage du monitoring système
     13
     14Pré-requis (Raspberry Pi):
     15* Outils de compilation croisée
     16* Configuration et utilisation des GPIO
     17
     18Ressources:
     19* newhaven display est le fabriquant du module LCD, c'est donc, en principe la référence.
     20  * 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
     21    d'initialisation du LCD décrite dans la documentation du [[http://www.newhavendisplay.com/app_notes/ST7066U.pdf | ST7006U]]
     22    ne fonctionne pas...
     23* HD44780 est le contrôleur historique de la majorité des LCD de ce genre. La procédure d'initialisation fonctionne.
     24  * [[http://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller | LCD Display HD44780]]
     25    [[https://www.sparkfun.com/datasheets/LCD/HD44780.pdf | Datasheet du HD44780]]
     26* Le document suivant définit comment est adressé la mémoire "vidéo" du LCD.
     27  * [[http://web.alfredstate.edu/faculty/weimandn/lcd/lcd_addressing/lcd_addressing_index.html | Adressage de la mémoire interne de l'afficheur]]
     28
     29Prenez le temps de parcourir les documents sur les afficheurs avant de commencer le TP.
     30
     31Le code à modifier se trouve en pièces jointes de cette page [[attachment:lcd_user.c]] et [[attachment:Makefile]]. Vous pourrez les copier dans un répertoire `TP4/lcd_user/`
     32
     33== 1. Configuration des GPIO pour le pilotage de l'écran ==
     34
     35L'é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.
     36
     37Dans 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).
     38
     39Les signaux de contrôle RS et E sont utilisés de la manière suivante:
     40* 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).
     41* 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.
     42
     43Voici le mapping des GPIO pour les différents signaux:
     44
     45||=   Signal LCD  =||=     GPIO     =||
     46||       RS        ||       7        ||
     47||       E         ||       27       ||
     48|| D4, D5, D6, D7  || 22, 23, 24, 25 ||
     49
     50Pour contrôler l'afficheur nous devons répondre aux questions ci-après. Les réponses à ces questions se trouve dans la documentation de l'afficheur. Les réponses sont partiellement données dans les morceaux de codes mais vous devez quand même comprendre ce que vous faites.
     51* Comment faut-il configurer les GPIOs pour les différents signaux de l'afficheur LCD ?
     52* Comment écrire des valeurs vers le LCD ?
     53* Quelles valeurs doivent être envoyées vers l'afficheur pour réaliser l'initialisation ?
     54* Comment demander l'affichage d'un caractère ?
     55* Comment envoyer des commandes telles que : l'effacement de l'écran, le déplacement du curseur, etc. ?
     56
     57Page 11 de la documentation : [[http://www.newhavendisplay.com/specs/NHD-0420DZ-FL-YBW.pdf | Datasheet du LCD de la plateforme]]
     58* 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).
     59* 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).
     60* R_W est un registre dont l'état est recopié sur RW
     61* Delay() est une attente en microsecondes.
     62
     63{{{#!c
     644-bit Initialization:
     65/**********************************************************/
     66void command(char i)
     67{
     68  P1 = i;                       //put data on output Port
     69  D_I =0;                       //D/I=LOW : send instruction
     70  R_W =0;                       //R/W=LOW : Write       
     71  Nybble();                     //Send lower 4 bits
     72  i = i<<4;                     //Shift over by 4 bits
     73  P1 = i;                       //put data on output Port
     74  Nybble();                     //Send upper 4 bits
     75}
     76/**********************************************************/
     77void write(char i)
     78{
     79  P1 = i;                       //put data on output Port
     80  D_I =1;                       //D/I=HIGH : send data
     81  R_W =0;                       //R/W=LOW : Write   
     82  Nybble();                     //Clock lower 4 bits
     83  i = i<<4;                     //Shift over by 4 bits
     84  P1 = i;                       //put data on output Port
     85  Nybble();                     //Clock upper 4 bits
     86}
     87/**********************************************************/
     88void Nybble()
     89{
     90  E = 1;
     91  Delay(1);                     //enable pulse width  >= 300ns
     92  E = 0;                        //Clock enable: falling edge
     93}
     94/**********************************************************/
     95void init()
     96{
     97  P1 = 0;
     98  P3 = 0;
     99  Delay(100);                   //Wait >40 msec after power is applied
     100  P1 = 0x30;                    //put 0x30 on the output port
     101  Delay(30);                    //must wait 5ms, busy flag not available
     102  Nybble();                     //command 0x30 = Wake up 
     103  Delay(10);                    //must wait 160us, busy flag not available
     104  Nybble();                     //command 0x30 = Wake up #2
     105  Delay(10);                    //must wait 160us, busy flag not available
     106  Nybble();                     //command 0x30 = Wake up #3
     107  Delay(10);                    //can check busy flag now instead of delay
     108  P1= 0x20;                     //put 0x20 on the output port
     109  Nybble();                     //Function set: 4-bit interface
     110  command(0x28);                //Function set: 4-bit/2-line
     111  command(0x10);                //Set cursor
     112  command(0x0F);                //Display ON; Blinking cursor
     113  command(0x06);                //Entry Mode set
     114}
     115/**********************************************************/
     116}}}
     117
     118== 2. Fonctionnement de l'écran et fonctions de base ==
     119
     120La prise en compte de la donnée est réalisée lors d'un front descendant du signal E.
     121Pour créer un front descendant:
     122* on place la donnée,
     123* puis le signal E est mis à 1 pendant 1µs puis remis à 0 pendant une 1µs supplémentaire pour garantir le délai entre deux commandes.
     124
     125||**Question:**\\Compléter la fonction lcd_strobe (nommée nybble dans le cours) qui permet de générer le signal E.
     126
     127[[Image(htdocs:png/command_lcd.png, width=900px, nolink)]]
     128
     129Nous 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.
     130
     131||**Question:**\\Compléter la fonction lcd_write4bits en vous aidant du cours.
     132
     133Nous 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.
     134
     135||**Question:**\\Compléter la fonction lcd_init qui réalise la séquence d'initialisation telle que vue en cours. Vérifiez son fonctionnement sur une carte Raspberry Pi. Vous devez être en mode 4 bits, 2 lignes, matrix5x8 ; allumer l'écran sans curseur ; demander d'écrire de gauche à droite sans déplacement des caractères.
     136
     137Vous êtes prêt à tester votre code et vérifier qu'il affiche correctement une chaine de caractère.
     138
     139||**Question:**\\Ecrivez un programme qui affiche la chaine de caractère "Hello World" sur l'afficheur. Vérifiez son fonctionnement sur une carte Raspberry Pi.
     140
     141Il peut être utile de manipuler la position du curseur pour choisir où placer les caractères sur l'afficheur.
     142
     143Pour 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).
     144
     145La mémoire DDRAM est construite de la manière suivante:
     146||0x00 ..... Ligne 1 ..... 0x13||
     147||0x40 ..... Ligne 2 ..... 0x53||
     148||0x14 ..... Ligne 3 ..... 0x27||
     149||0x54 ..... Ligne 4 ..... 0x67||
     150
     151On souhaites utiliser toutes les lignes
     152
     153|| **Question:**\\1. Ecrire une fonction lcd_set_cursor qui positionne le curseur aux coordonnées (x,y) avec x la colonne, y la ligne.\\2. Ecrire un programme qui affiche "Hello World" sur chacune des lignes de l'afficheur.
     154
     155== 4. Driver pour le LCD ==
     156
     157Reprenez le pilote que vous aviez écrit pour les leds et modifiez la commande `write` de telle sorte que si vous appelez votre device /dev/lcd_xy (où xy sont les initiales de votre binôme), vous puissiez écrire.
     158{{{#!bash
     159$ echo "Bonjour" > /dev/lcd_xy
     160}}}
     161
     162Vous allez devoir remplacer usleep() par udelay() et ajouter un `#include <asm/delay.h>` au début du code de votre module (merci Arthur).
     163
     164}}}