IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Raspberry Pi Discussion :

Ecran GDM2004D et expandeur PCF8574


Sujet :

Raspberry Pi

  1. #1
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut Ecran GDM2004D et expandeur PCF8574
    Bonjour,
    je veux utiliser un écran GDM200D en mode bus 4 bits avec un expandeur de bus I2C PCF8574.
    J'utilise wiringPi I2C et son extension dédiée pour le 8574 en écrivant d'abord le quartet de poids de mes octets (commande et donnée) et en pilotant en parallèle les signaux de commande (RW, RS, EN et BACKLIGHT).
    Mon code:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    #define I2C_SCREEN_ADDRESS	0x27
    #define LCD_BACKLIGHT 0x08
    #define EN 	0x04	//ENable bit 
    #define RW	0x02	//RW bit
    #define RS	0x01	//RS bit
     
    #define DISPLAY_OFF	0x00
    #define CLEAR_DISPLAY	0x01
    #define HOME_CURSOR	0x02
    #define MODE_SET	0x60
    #define DISPLAY_ON	0xC0
    #define DISPLAY_SHIFT	0x14
    #define FUNCTION_SET	0x28
     
    int main()
    {
      int fd_screen;
     
      wiringPiSetup();
      fd_screen = wiringPiI2CSetup(I2C_SCREEN_ADDRESS);
      pcf8574Setup(69, I2C_SCREEN_ADDRESS);
      if(fd_screen < 0)
      {
        perror("I2C Setup");
        exit(EXIT_FAILURE);
      }
     
      lcd_write_cmd(fd_screen, CLEAR_DISPLAY);
      lcd_write_cmd(fd_screen, HOME_CURSOR);
      lcd_write_cmd(fd_screen, MODE_SET);
      lcd_write_cmd(fd_screen, DISPLAY_ON);
      lcd_write_cmd(fd_screen, DISPLAY_SHIFT);
      lcd_write_cmd(fd_screen, FUNCTION_SET);
     
      //Afficher les caractères A, B et C
      lcd_write_data(fd_screen, 'A');
      lcd_write_data(fd_screen, 'B');
      lcd_write_data(fd_screen, 'C');
     
      //pour test, forcer BACKLIGHT à 0 pour éteindre l'écran
      printf("Display OFF dans 2s.\n");
      sleep(2);
      wiringPiI2CWrite(fd_screen, DISPLAY_OFF);
     
      exit(EXIT_SUCCESS);
    }
     
    /******************************************************************************
     * lcd_write_cmd(): ecriture d'une commande vers l'écran. Pour une commande,
     * RS = 1, RW = 0, LCD_BACKLIGHT = 1, EN = 1 puis 0 pour valider
     * Entrée: fd_screen, descripteur de fichier du port I2C; data, donnée à écrire
     * Sortie:
     * ***************************************************************************/
    void lcd_write_cmd(int fd_screen, unsigned char data)
    {
      unsigned char cmd = 0;
    								                                                      //BL  EN  RW  RS
      wiringPiI2CWrite(fd_screen, ((LCD_BACKLIGHT | EN) & ~RS) & ~RW);        //1   1   0   0
      usleep(100);
      cmd = ((data & 0xF0) | (((LCD_BACKLIGHT | EN) & ~RS) & ~RW));	      //1   1   0   0
      wiringPiI2CWrite(fd_screen, cmd);
      usleep(100);
      cmd = ((data & 0xF0) | (((LCD_BACKLIGHT & ~EN) & ~RS) & ~RW));       //1   1   0   0
      wiringPiI2CWrite(fd_screen, cmd);				      //1   0   0   0
      usleep(100);
     
      wiringPiI2CWrite(fd_screen, ((LCD_BACKLIGHT | EN) & ~RS) & ~RW);          //1   1   0   0
      usleep(100);
      cmd = (((data << 4) & 0xF0) | (((LCD_BACKLIGHT | EN) & ~RS) & ~RW)); //1   1   0   0
      wiringPiI2CWrite(fd_screen, cmd);
      usleep(100);
      cmd = (((data << 4) & 0xF0) | (((LCD_BACKLIGHT & ~EN) & ~RS) & ~RW));//1   1   0   0
      wiringPiI2CWrite(fd_screen, cmd);				                                             //1   0   0   0
      usleep(100);
    }
     
    /******************************************************************************
     * lcd_write_data(): ecriture d'une donnée vers l'écran. Pour une donnée,
     * RS = 0, RW = 0, LCD_BACKLIGHT = 1, EN = 1 puis 0 pour valider
     * Entrée: fd_screen, descripteur de fichier du port I2C; data, donnée à écrire
     * Sortie:
     * ***************************************************************************/
    void lcd_write_data(int fd_screen, unsigned char data)
    {
      unsigned char dt;
     
      wiringPiI2CWrite(fd_screen, ((LCD_BACKLIGHT | EN) | RS) & ~RW);
      usleep(100);
      dt = ((data & 0xF0) | (((LCD_BACKLIGHT | EN) | RS) & ~RW));
      wiringPiI2CWrite(fd_screen, dt);
      usleep(100);
      dt = ((data & 0xF0) | (((LCD_BACKLIGHT & ~EN) | RS) & ~RW));
      wiringPiI2CWrite(fd_screen, dt);
      usleep(100);
     
      wiringPiI2CWrite(fd_screen, ((LCD_BACKLIGHT | EN) | RS) & ~RW);
      usleep(100);
      dt = (((data << 4) & 0xF0) | (((LCD_BACKLIGHT | EN) | RS) & ~RW));
      wiringPiI2CWrite(fd_screen, dt);
      usleep(100);
      dt = (((data << 4) & 0xF0) | (((LCD_BACKLIGHT & ~EN) | RS) & ~RW));
      wiringPiI2CWrite(fd_screen, dt);
      usleep(100);
    }
    Rien ne se passe à l'écran. La dernière ligne du main() arrive pourtant bien à éteindre l'écran. J'en déduis que wiringPiI2CWrite() fonctionne...
    Vu la doc, je pense que je respecte le chronogramme d'écriture sur le GDM2004D.
    Si quelqu'un a déjà utilisé cet écran avec cet expandeur, je prend toutes les remarques car je sèche!
    Merci.

  2. #2
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 185
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 185
    Points : 11 551
    Points
    11 551
    Par défaut
    Salut,
    Tu peux poster le schéma de câblage correspondant au code ?

    A+
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  3. #3
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Bonjour et merci pour la réponse.
    Le schéma de câblage:
    Nom : schemaCablage.png
Affichages : 336
Taille : 86,4 Ko
    Le chronogramme en écriture que j'utilise:

    Nom : chronoWrite.png
Affichages : 256
Taille : 37,4 Ko

    J'ai modifié mon code que je trouvais difficile à lire. J'espère ne pas avoir aggraver mon cas.
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
     
    int main()
    {
      int fd_screen;
     
      wiringPiSetup();
      fd_screen = wiringPiI2CSetup(I2C_SCREEN_ADDRESS);
      pcf8574Setup(69, I2C_SCREEN_ADDRESS);
      if(fd_screen < 0)
      {
        perror("I2C Setup");
        exit(EXIT_FAILURE);
      }
     
      printf("fd_screen = %d\n", fd_screen);
      printf("GD2004D screen tests.\n");
     
      //Function set: mode 4 bits --> 0x28
      lcd_write_cmd(fd_screen, FUNCTION_SET);
      lcd_write_cmd(fd_screen, CLEAR_DISPLAY);
      lcd_write_cmd(fd_screen, HOME_CURSOR);
      lcd_write_cmd(fd_screen, MODE_SET);
      lcd_write_cmd(fd_screen, DISPLAY_ON);
      lcd_write_cmd(fd_screen, DISPLAY_SHIFT);
     
      lcd_write_data(fd_screen, 'A');
     
      exit(EXIT_SUCCESS);
    }
     
    /******************************************************************************
     * lcd_write_cmd(): ecriture d'une commande vers l'écran. Pour une commande,
     * RS = 1, RW = 0, LCD_BACKLIGHT = 1
     * Entrée: fd_screen, descripteur de fichier du port I2C; data, donnée à écrire
     * Sortie:
     * ***************************************************************************/
    void lcd_write_cmd(int fd_screen, unsigned char data)
    {
      unsigned char ctrl = 0x08;	//BL=1 EN=0 RW=0 RS=0
      unsigned tmp;
     
      tmp = (data & 0xF0) | ctrl;
      printf("lcd_write_cmd: tmp = 0x%x\n", tmp);
      wiringPiI2CWrite(fd_screen, tmp);
      lcd_strobe(fd_screen, tmp);
     
      tmp = ((data << 4) & 0xF0) | ctrl;
      printf("lcd_write_cmd: tmp = 0x%x\n", tmp);
      wiringPiI2CWrite(fd_screen, tmp);
      lcd_strobe(fd_screen, tmp);
    }
     
    /******************************************************************************
     * lcd_write_data(): ecriture d'une donnée vers l'écran. Pour une donnée,
     * RS = 0, RW = 0, LCD_BACKLIGHT = 1
     * Entrée: fd_screen, descripteur de fichier du port I2C; data, donnée à écrire
     * Sortie:
     * ***************************************************************************/
    void lcd_write_data(int fd_screen, unsigned char data)
    {
      unsigned char ctrl = 0x09;	//BL=1 EN=0 RW=0 RS=1
     
      unsigned tmp = data;
      tmp = (data & 0xF0) | ctrl;
      printf("lcd_write_cmd: tmp = 0x%x\n", tmp);
      wiringPiI2CWrite(fd_screen, tmp);
      lcd_strobe(fd_screen, tmp);
     
      tmp = ((data << 4) & 0xF0) | ctrl;
      printf("lcd_write_cmd: tmp = 0x%x\n", tmp);
      wiringPiI2CWrite(fd_screen, tmp);
      lcd_strobe(fd_screen, tmp);
    }
     
    void lcd_strobe(int fd_screen, unsigned char data)
    {
      printf("lcd_strobe: data = 0x%x\n", data | EN);
      wiringPiI2CWrite(fd_screen, data | EN);
      usleep(100);
      printf("lcd_strobe: data = 0x%x\n", data & ~EN);
      wiringPiI2CWrite(fd_screen, (data & ~EN));
      usleep(100);
    }

    je trace l'état des broches de commande via des printf. Ca me semble correct. Je n'ai pas la possibilité d'utiliser un oscilloscope.
    Une chose qui m'étonne c'est qu'il faut configurer logiciellement l'écran en mode 4 bits. Mais quand je le configure, dans quel mode est-il?

    Merci pour le temps passé.

  4. #4
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Bonjour,
    je pilote correctement le signal BT puisque je peux faire "clignoter" l'écran avec quelques lignes de code.
    Qu'est ce que je peux en déduire au point de vue de la chaîne: monProgramme --> PCF8574 --> HD44780 qui est le circuit d'interface de l'écran?

    Merci.

  5. #5
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 185
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 185
    Points : 11 551
    Points
    11 551
    Par défaut
    Re,
    C'est toi qui a défini les #define ? Parce que je ne trouve pas les mêmes valeurs que toi en comparant avec ton schéma.
    Je trouve deux erreurs, voir plus bas.




    #define DISPLAY_OFF 0x00 OK !

    #define CLEAR_DISPLAY 0x01 OK !

    #define HOME_CURSOR 0x02 OK !

    #define MODE_SET 0x60 pour moi ce n'est pas ça, ça devrait aller de 0x04 à 0x07 suivant l'état des bits I/D et S que tu souhaites.

    Instructions RS R/W D7 D6 D5 D4 D3 D2 D1 D0 Description
    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 1re position à gauche, 1re ligne.

    #define DISPLAY_ON 0xC0 pour moi ce n'est pas bon, ça devrait aller de 0x08 à 0x0F

    Instructions RS R/W D7 D6 D5 D4 D3 D2 D1 D0 Description
    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

    #define DISPLAY_SHIFT 0x14 OK !

    #define FUNCTION_SET 0x28 OK !
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  6. #6
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Bonjour.
    Désolé, je n'ai pas reposté l'intégralité de mon code mais j'avais modifié ces valeurs:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define MODE_SET 0x06
    #define DISPLAY_ON 0x0C

    Mais ça ne fonctionne toujours pas.
    Dans mon code, je positionne les données et après je fais monter E, ce qui n'est pas conforme au chronogramme. Mais justement, il ne dit rien à propos d'un temps à respecter entre le front montant de E et le positionnement de ces données.

  7. #7
    Modérateur

    Avatar de Vincent PETIT
    Homme Profil pro
    Consultant en Systèmes Embarqués
    Inscrit en
    Avril 2002
    Messages
    3 185
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Systèmes Embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 185
    Points : 11 551
    Points
    11 551
    Par défaut
    Salut,
    J'allais justement arriver à cette histoire de "Enable" mais avant cela, est ce que tu as un voltmètre chez toi ? Même un truc à 10€ qui viendrait d'un magasin de bricolage. Je te le demande car quand on met quelque chose au point dans un système embarqué, on peut rapidement tourner en rond et être complètement bloqué. En revanche en y allant par étape on évite quasiment tous les pièges. Si tu as un multimètre, il serait intéressant de faire un soft hyper simple qui envoi une, et une seule, commande au LCD et de vérifier si on a au moins les bonnes tensions (les bons états logiques) sur le LCD. Ça validera la partie soft qui balance la commande vers l'afficheur.

    Concernant "Enable", tel qu'on voit le chronogramme, il faut :
    - positionner RS
    - positionner R/W
    - faire un front montant sur E pour valider RS et R/W (le chronogramme dit que RS et R/W doivent être fixés pendant au moins tsu1 avant un front montant de E)
    - [*] positionner la commande/donnée
    - [*] faire un front descendant sur E pour valider les données (le chronogramme dit que les données doivent être fixées pendant au moins tsu2 avant un front descendant de E)

    * en mode 4 bits, il faut répéter deux fois cette étape, d'abord le quartet de poids fort des données, puis celui de poids faible.

    Je ne suis pas sur que c'est ce que ton code fait ?
    La science ne nous apprend rien : c'est l'expérience qui nous apprend quelque chose.
    Richard Feynman

  8. #8
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Bonjour,
    je vais modifier mon code pour prendre en compte ta remarque concernant le signal E.
    Je posterai le résultat de mes printf, mais je pense bien présenter le quartet de poids fort avant celui de poids faible.
    Mais je dois attendre jeudi pour accéder au matériel. Je devrais avoir un oscillo à disposition pour faire des vérifications plus poussées.
    Merci.

  9. #9
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    289
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2008
    Messages : 289
    Points : 151
    Points
    151
    Par défaut
    Bonjour,
    j'ai sorti l'oscilloscope, les signaux respectent les chronogrammes de la datasheet avec poids forts puis poids faibles.
    J'ai tenté moult combinaisons de configuration mais j'envisage maintenant que l'écran soit défectueux...
    Je clos la discussion le temps de faire l'acquisition d'un autre écran et j'aurai donc peut-être l'occasion de revenir.

    Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ecran tactile
    Par fabricep dans le forum Delphi
    Réponses: 9
    Dernier message: 16/09/2006, 13h40
  2. [VB6] Touche impr écran
    Par SpaceFrog dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 12/11/2002, 08h38
  3. Comment faire pour mettre l'ecran en veille ?
    Par March' dans le forum MFC
    Réponses: 6
    Dernier message: 29/08/2002, 15h25
  4. Copier et afficher une copie d'ecran
    Par Bobx dans le forum Langage
    Réponses: 6
    Dernier message: 02/08/2002, 23h20
  5. [TP]lire une ligne de l'ecran et la stocker dans une chaine
    Par Bleuarff dans le forum Turbo Pascal
    Réponses: 26
    Dernier message: 02/07/2002, 11h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo