Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1704 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2  3  4  5  6  7  8
Auteur Sujet :

[ Divers / C ] Ecrire pour un afficheur LCD

n°2109038
Profil sup​primé
Posté le 01-11-2011 à 12:35:08  answer
 

Reprise du message précédent :
Mon led pour RS était soudé sur 17... ET 16 [:spamafate]
Du coup, le test original fonctionne en fait
Par contre dans le code du pilote, RS ne s'allume toujours pas.
A moins que t'ai pas mis de délay après une mise à 1 de RS.

mood
Publicité
Posté le 01-11-2011 à 12:35:08  profilanswer
 

n°2109041
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 13:18:52  profilanswer
 

Citation :

Mon led pour RS était soudé sur 17... ET 16

[:aless]  
 
 :D  
 

Citation :

Du coup, le test original fonctionne en fait


 
Le code de test que j'ai initialement posté?
 

Citation :

Par contre dans le code du pilote, RS ne s'allume toujours pas.

Normal, il n'y a que des écritures, donc il reste a 0.
Il n'est a 1 que comme paramètre en lecture, quand RW est a 1.
Dans le code du pilote, il devrait y avoir que le strobe qui passe de 0 a 1, puis revient a 0.
Tout le reste est au niveau des datas.
 
Bon alors, il fait quelque chose, l'afficheur? Parce que si le code de test original marche, le pilote devrait être OK, a mes erreurs de frappe près (style taper 0x40 quand je voulais taper 0x04)
 
A+,

Message cité 1 fois
Message édité par gilou le 01-11-2011 à 13:21:50

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109045
Profil sup​primé
Posté le 01-11-2011 à 13:57:53  answer
 

gilou a écrit :


 

Citation :

Du coup, le test original fonctionne en fait


 
Le code de test que j'ai initialement posté?


Oui, le code de teste de EWS fonctionne.

gilou a écrit :


Normal, il n'y a que des écritures, donc il reste a 0.
Il n'est a 1 que comme paramètre en lecture, quand RW est a 1.
Dans le code du pilote, il devrait y avoir que le strobe qui passe de 0 a 1, puis revient a 0.
Tout le reste est au niveau des datas.


0k !

gilou a écrit :


Bon alors, il fait quelque chose, l'afficheur? Parce que si le code de test original marche, le pilote devrait être OK, a mes erreurs de frappe près (style taper 0x40 quand je voulais taper 0x04)
 
A+,


 
j'ai mis une pause entre LCD_Display et LCD_WriteString et entre ce dernier est Restore., j'ai le curseur. Mais j'ai pas la chaîne. Et restore semble éteindre l'écran.
 
J'ai changé les outb_p en outb. Que je mette 100 ou 1000 dans delay ça change pas.
 
Désolé pour les soudures.  :heink:  
 
 

n°2109046
Profil sup​primé
Posté le 01-11-2011 à 13:59:34  answer
 

Mais ça marche pas à tout les coups.
 
Je reboote pour mettre au clair.

n°2109048
Profil sup​primé
Posté le 01-11-2011 à 14:09:13  answer
 

J'ai pas eu le temps de lire correctement ton code, surtout que je connais pas le C.
J'ai rebooté, j'ai tout mis à zéro avant de tester le prog, maintenant ça marche à tout les coups.
C'est à dire qu'à tout les coup le curseur apparaît à LCD_Display(1, 1, 1) et disparaît lors que LCD_WriteString() mais pas de chaîne à l'horizon.

n°2109049
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 14:13:21  profilanswer
 

A oui, tu mets une pause sleep (20), ou bien une une attente d'un appui clavier après le LCD_WriteString
 
char buffer [256];
printf("Tapez Q pour quitter\n" );
gets(buffer);
 
parce qu'après, on sort tout de suite du programme.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109050
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 14:16:16  profilanswer
 


On progresse! ça nous dit déjà que le code marche pour envoyer les datas au LCD puisque le code de commande de l'allumage de l'écran est dans les datas.
 
Un LCD_WriteChar('J'); au lieu du LCD_WriteString("Jovalise" ); ça met un caractère?
 
 
A+,


Message édité par gilou le 01-11-2011 à 14:18:28

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109052
Profil sup​primé
Posté le 01-11-2011 à 14:24:25  answer
 

Euh...
 
La modification de la chaîne envoyé, modifi le comportement de LCD_Display.  :o   :pt1cable:  
 
La j'ai mis "Jovalise et Gilou !" et le curseur apparaît, si je met "Jovalise" ça marche plus.
Avecjuste "J" ça marche plus non plus.
 
 :pt1cable: 2

n°2109053
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 14:25:02  profilanswer
 

Ah j'ai pigé: quand on écrit un caractère, il faut mettre le bit RS a 1.
Je m'en occupe!
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109055
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 14:37:38  profilanswer
 

Code :
  1. // On écrit un caractère
  2. void LCD_WriteChar(char c) {
  3.     unsigned char oldctl, ctl;
  4.     // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  5.     oldctl = ctl = inb(CONTROLREG);
  6.     ctl &= 0xD0;  // Bits du haut: direction mise à 0 (écriture) et bits du bas à 0
  7.     ctl |= 0x03;  // On force le bas à 0011 ce qui va mettre tout RS a 1 en sortie pour les valeurs de controle
  8.     if (oldctl != ctl) { // on met pas a jour si c'est déjà bon
  9. outb(ctl, CONTROLREG);
  10. delay(2);
  11.     }
  12.     // 2) Mise de la valeur dans le registre data
  13.     outb_p(c, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  14.     // si outb_p ne plante pas
  15.     // 3) envoi d'un strobe pour signaler au LCD une commande
  16.     ctl &= 0xFE; // registre strobe mis a 0 => signal strobe haut en sortie
  17.     outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  18.     delay(2);
  19.     ctl |= 0x01; // registre strobe mis a 1 => signal strobe bas en sortie
  20.     outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  21.     delay(2);
  22. }
  23. // On écrit une chaine
  24. void LCD_WriteString(char *s) {
  25.     unsigned char oldctl, ctl;
  26.     // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  27.     oldctl = ctl = inb(CONTROLREG);
  28.     ctl &= 0xD0;  // Bits du haut: direction mise à 0 (écriture) et bits du bas à 0
  29.     ctl |= 0x03;  // On force le bas à 0011 ce qui va mettre RS a 1 en sortie pour les valeurs de controle
  30.     if (oldctl != ctl) { // on met pas a jour si c'est déjà bon
  31. outb(ctl, CONTROLREG);
  32. delay(2);
  33.     }
  34.     while (*s) {
  35. // Mise du caractère dans le registre data
  36. outb_p(*s, DATAREG);
  37. // si outb_p ne plante pas
  38. // 3) envoi d'un strobe pour signaler au LCD une commande
  39. ctl &= 0xFE;
  40. outb(ctl, CONTROLREG);
  41. delay(2);
  42. ctl |= 0x01;
  43. outb(ctl, CONTROLREG);
  44. delay(2);
  45. s++;
  46.     }
  47. }


Avec ces deux fonctions à la place des anciennes, ca devrait marcher.
Pour LCD_WriteString on remplace juste le ctl |= 0x0B; par ctl |= 0x03;
et pour le LCD_WriteChar on remplace son contenu par celui de data_write, on y renomme le paramètre data en c, et on fait la même modif que pour LCD_WriteString:  on remplace juste le ctl |= 0x0B; par ctl |= 0x03;
 
A+,

Message cité 1 fois
Message édité par gilou le 01-11-2011 à 14:39:53

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
mood
Publicité
Posté le 01-11-2011 à 14:37:38  profilanswer
 

n°2109056
Profil sup​primé
Posté le 01-11-2011 à 14:48:54  answer
 

gilou a écrit :

Ah j'ai pigé: quand on écrit un caractère, il faut mettre le bit RS a 1.
Je m'en occupe!
A+,


 
Ben, c'est ce que j'aurais fait par défaut, puisque c'est ce que je lis dans le code de Linux magasine. (en première page)
 
 

gilou a écrit :

Code :
  1. // On écrit un caractère
  2. void LCD_WriteChar(char c) {
  3.     unsigned char oldctl, ctl;
  4.     // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  5.     oldctl = ctl = inb(CONTROLREG);
  6.     ctl &= 0xD0;  // Bits du haut: direction mise à 0 (écriture) et bits du bas à 0
  7.     ctl |= 0x03;  // On force le bas à 0011 ce qui va mettre tout RS a 1 en sortie pour les valeurs de controle
  8.     if (oldctl != ctl) { // on met pas a jour si c'est déjà bon
  9. outb(ctl, CONTROLREG);
  10. delay(2);
  11.     }
  12.     // 2) Mise de la valeur dans le registre data
  13.     outb_p(c, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  14.     // si outb_p ne plante pas
  15.     // 3) envoi d'un strobe pour signaler au LCD une commande
  16.     ctl &= 0xFE; // registre strobe mis a 0 => signal strobe haut en sortie
  17.     outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  18.     delay(2);
  19.     ctl |= 0x01; // registre strobe mis a 1 => signal strobe bas en sortie
  20.     outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  21.     delay(2);
  22. }
  23. // On écrit une chaine
  24. void LCD_WriteString(char *s) {
  25.     unsigned char oldctl, ctl;
  26.     // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  27.     oldctl = ctl = inb(CONTROLREG);
  28.     ctl &= 0xD0;  // Bits du haut: direction mise à 0 (écriture) et bits du bas à 0
  29.     ctl |= 0x03;  // On force le bas à 0011 ce qui va mettre RS a 1 en sortie pour les valeurs de controle
  30.     if (oldctl != ctl) { // on met pas a jour si c'est déjà bon
  31. outb(ctl, CONTROLREG);
  32. delay(2);
  33.     }
  34.     while (*s) {
  35. // Mise du caractère dans le registre data
  36. outb_p(*s, DATAREG);
  37. // si outb_p ne plante pas
  38. // 3) envoi d'un strobe pour signaler au LCD une commande
  39. ctl &= 0xFE;
  40. outb(ctl, CONTROLREG);
  41. delay(2);
  42. ctl |= 0x01;
  43. outb(ctl, CONTROLREG);
  44. delay(2);
  45. s++;
  46.     }
  47. }


Avec ces deux fonctions à la place des anciennes, ca devrait marcher.
Pour LCD_WriteString on remplace juste le ctl |= 0x0B; par ctl |= 0x03;
et pour le LCD_WriteChar on remplace son contenu par celui de data_write, on y renomme le paramètre data en c, et on fait la même modif que pour LCD_WriteString:  on remplace juste le ctl |= 0x0B; par ctl |= 0x03;
 
A+,


 
Ouh... Ca brule.
 
J'ai d'abord eu un caractère plein qui clignote en contraste, (tu va peut-être comprendre, moi je suis un poil à la ramasse)
Bon, c'est le curseur.
A l'affichage de la chaîne "G" , j'ai eu deux caractère plein avec dans le premier un "G" en contraste.
Et après la fin du programme, j'ai plus que "G" en claire, plus un trait bas en second caractère.
 
Je teste une chaîne plus longue... T'as triché ou quoi ?
 
 
 

n°2109057
Profil sup​primé
Posté le 01-11-2011 à 14:55:08  answer
 


 
 
Ca affiche la chaîne un 5ieme de seconde et ça s'éteint... Pourtant j'ai un sleep(10) après le LCD_Write string.

n°2109060
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 15:02:03  profilanswer
 


Plutôt qu'un sleep met un getchar(); ça va attendre un appui clavier quelconque avant de poursuivre le programme.
 
>> J'ai d'abord eu un caractère plein qui clignote en contraste, (tu va peut-être comprendre, moi je suis un poil à la ramasse)  
C'est le LCD_Display(1, 1, 1);  
>> Et après la fin du programme, j'ai plus que "G" en claire, plus un trait bas en second caractère.  
C'est ce qu'on doit avoir: le caractere écrit et le curseur qui a avancé d'un cran  
 
On y est presque en tout cas!
 
A+,


Message édité par gilou le 01-11-2011 à 15:03:08

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109064
Profil sup​primé
Posté le 01-11-2011 à 15:11:56  answer
 

J'ai mis "Gilou et Jovalise ! " [:powa]
 
 
Ca affiche "Ginow gv Nova|N(natas char)Wg ! "  :lol:  :D  :whistle:  
 
Je me trouve le curseur sur la 3ième lignes.  :jap:  
 
Mais normalement d'après les résultat précédent, ça devrait pas être aussi clair.  :heink:
 
 
Et après le getchar() c'est comme réinitialisé, sauf que je vois encore le texte en contraste.(des caratère plein avec le même texte mais dans le contraste.


Message édité par Profil supprimé le 01-11-2011 à 15:14:07
n°2109065
Profil sup​primé
Posté le 01-11-2011 à 15:19:25  answer
 

Merci Gilou en tout cas. J'ai pas d'appareil photo.  [:karlu]  
 
Ca jette.
 
Pour le code, j'ai corrigé ce que tu a donné avec des outb à la place et outb_p.
Puis deux varible non déclarée et une faute de frappe.  
 
 :jap:  :jap:  :jap:


Message édité par Profil supprimé le 01-11-2011 à 15:20:07
n°2109066
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 15:24:36  profilanswer
 

>> Je me trouve le curseur sur la 3ième lignes.
Normal ça, chaque ligne fait 20 caractères, et après le 20e de la ligne 1, ça va sur le premier de la ligne 3 (et idem pour les lignes 2 et 4)
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109068
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 15:34:10  profilanswer
 

>> Pour le code, j'ai corrigé ce que tu a donné avec des outb à la place et outb_p;
ajoutes un delay(2) après. J'ai l'impression que ce qui était écrit déconne parce qu'on attends pas assez longtemps que tout soit lu et transféré.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109073
Profil sup​primé
Posté le 01-11-2011 à 15:59:40  answer
 

gilou a écrit :

>> Pour le code, j'ai corrigé ce que tu a donné avec des outb à la place et outb_p;
ajoutes un delay(2) après. J'ai l'impression que ce qui était écrit déconne parce qu'on attends pas assez longtemps que tout soit lu et transféré.
 
A+,


 
 
Nan.  ;)  
 
Je je penche sur un afficheur mort ou des soudure pourrite.  :jap:  

n°2109075
Profil sup​primé
Posté le 01-11-2011 à 16:08:02  answer
 

Le code ici.
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/io.h>
  5. // Base port cablé sur LPT1 ici
  6. #define BASEPORT    0x378
  7. #define DATAREG     BASEPORT+0
  8. #define STATUSREG   BASEPORT+1
  9. #define CONTROLREG  BASEPORT+2
  10. // delai d'attente en ms  
  11. void delay(int mstime) {
  12.  usleep(mstime * 100);
  13. }
  14. // Initialisation des registres, sauvegarde du registre de controle
  15. unsigned char init_port() {
  16.  unsigned char oldctl, ctl;
  17.  // 1) mise à  0 des datas. Ainsi, même si le 2 déclenche un strobe, il n'aura pas d'effet
  18.  outb(0x00, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  19.  delay(2);
  20.  // si outb_p ne plante pas
  21.  // 2) Mise a jour du registre des valeurs des pins de controle si necessaire
  22.  oldctl = ctl = inb(CONTROLREG);
  23.  ctl &= 0xD0;  // Bits du haut: direction mise à  0 (écriture) et bits du bas à  0
  24.  ctl |= 0x0B;  // On force le bas à  1011 ce qui va mettre tout à  0 en sortie pour les valeurs de controle
  25.  if (oldctl != ctl) { // on met pas a jour si c'est déjà  bon
  26.    outb(ctl, CONTROLREG);
  27.    delay(2);
  28.    delay(2);
  29.  }
  30.  return oldctl;
  31. }
  32. // Restauration du registre de controle
  33. void restore_port(unsigned char oldctl) {
  34.  unsigned char ctl;
  35.  // 1) mise à  0 des datas. Ainsi, même si le 2 déclenche un strobe, il n'aura pas d'effet
  36.  outb(0x00, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  37.  delay(2);
  38.  // si outb_p ne plante pas
  39.  // 2) Mise a jour du registre des valeurs des pins de controle si necessaire
  40.  ctl = inb(CONTROLREG);
  41.  if (oldctl != ctl) { // on met pas a jour si c'est déjà  bon
  42.    outb(oldctl, CONTROLREG);
  43.    delay(2);
  44.    delay(2);
  45.  }
  46. }
  47. // Envoi de commandes et données SPP -> LCD
  48. void data_write(unsigned char data) {
  49.  unsigned char oldctl, ctl;
  50.  // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  51.  oldctl = ctl = inb(CONTROLREG);
  52.  ctl &= 0xD0;  // Bits du haut: direction mise à  0 (écriture) et bits du bas à  0
  53.  ctl |= 0x0B;  // On force le bas à  1011 ce qui va mettre tout à  0 en sortie pour les valeurs de controle
  54.  if (oldctl != ctl) { // on met pas a jour si c'est déjà  bon
  55.    outb(ctl, CONTROLREG);
  56.    delay(2);
  57.    delay(2);
  58.  }
  59.  
  60.  // 2) Mise de la valeur dans le registre data
  61.  outb(data, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  62.  delay(2);
  63.  // si outb_p ne plante pas
  64.  // 3) envoi d'un strobe pour signaler au LCD une commande
  65.  ctl &= 0xFE; // registre strobe mis a 0 => signal strobe haut en sortie
  66.  outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  67.  delay(2);
  68.  delay(2);
  69.  ctl |= 0x01; // registre strobe mis a 1 => signal strobe bas en sortie
  70.  outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  71.  delay(2);
  72.  delay(2);
  73. }
  74.  
  75. // Lecture de donnée LCD -> SPP
  76. // ram positionné: on lit la valeur de la donnée en ram du LCD a l'adresse courante. associé à  RS a 1 en sortie
  77. // ram non positionné: on lit la valeur de l'adresse courante du LCD et le flag busy en poids fort. associé à  RS a 0 en sortie
  78. unsigned char data_read(int ramdata) {
  79.  unsigned char data;
  80.  unsigned char oldctl, ctl;
  81.  // 1) mise à  0 des datas. C'est peut être inutile
  82.  outb(0x00, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  83.  delay(2);
  84.  // si outb_p ne plante pas
  85.  // 2) Mise a jour du registre des valeurs des pins de controle si necessaire
  86.  oldctl = ctl = inb(CONTROLREG);
  87.  ctl &= 0xF0;  // Bits du bas à  0
  88.  ctl |= 0x20;  // Bits du haut: direction mise à  1 (écriture)  
  89.  if (ramdata) {
  90.    ctl |= 0x03;  // On force le bas à  0001 ce qui va mettre RW et RS a 1 en sortie et le reste à  0  
  91.  } else {
  92.    ctl |= 0x09;  // On force le bas à  1001 ce qui va mettre RW a 1 en sortie et le reste à  0  
  93.  }
  94.  if (oldctl != ctl) { // on met pas a jour si c'est déjà  bon
  95.    outb(ctl, CONTROLREG);
  96.    delay(2);
  97.    delay(2);
  98.  }
  99.  // 3) envoi d'un strobe pour signaler au LCD une commande
  100.  ctl &= 0xFE; // registre strobe mis a 0 => signal strobe haut en sortie
  101.  outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  102.  delay(2);
  103.  delay(2);
  104.  ctl |= 0x01; // registre strobe mis a 1 => signal strobe bas en sortie
  105.  outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  106.  delay(2);
  107.  delay(2);
  108.  // 4) lecture des données
  109.  if (ramdata) { // temps de lecture en RAM du LCD  
  110.    delay(1);
  111.  }
  112.  data = inb(DATAREG);
  113.  return data;
  114. }
  115. // Commandes admissibles par le LCD
  116. // Le bit non nul le plus haut détermine la commande
  117. // A priori, 00000000 -> Rien
  118. // 00000001 -> LCD Clear
  119. void LCD_Clear() {
  120.  unsigned char command = 0x01;  // Clear command
  121.  data_write(command);
  122.  delay(2);
  123. }
  124. // 0000001x -> LCD Home
  125. void LCD_Home() {
  126.  unsigned char command = 0x02;  // Home command
  127.  data_write(command);
  128.  delay(2);
  129. }
  130. // 000001xx -> LCD EntryMode
  131. void LCD_EntryMode(int lr, int shift) {
  132.  unsigned char command = 0x04;  // Entry Mode command
  133.  if (lr)      command |= 0x02; // Left -> Right [else Right Left] default
  134.  if (shift)   command |= 0x01; // Shift visible  
  135.  data_write(command);
  136.  delay(2);
  137. }
  138. // 00001xxx -> LCD Display
  139. void LCD_Display(int on, int cursor, int blink) {
  140.  unsigned char command = 0x08;  // DISPLAY command
  141.  if (on)      command |= 0x04; // Display on/off bit
  142.  if (cursor)  command |= 0x02; // Cursor on/off bit
  143.  if (blink)   command |= 0x01; // Cursor blink on/off bit
  144.  data_write(command);
  145.  delay(2);
  146. }
  147.  
  148. // 01xxxxxx -> LCD Set CGRAM
  149. // 1xxxxxxx -> LCD Set DDRAM
  150. // Routines d'un peu plus haut niveau
  151. // On écrit un caractère
  152. void LCD_WriteChar(char c) {
  153.  unsigned char oldctl, ctl;
  154.  // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  155.  oldctl = ctl = inb(CONTROLREG);
  156.  ctl &= 0xD0;  // Bits du haut: direction mise à  0 (écriture) et bits du bas à  0
  157.  ctl |= 0x03;  // On force le bas à  0011 ce qui va mettre tout RS a 1 en sortie pour les valeurs de controle
  158.  if (oldctl != ctl) { // on met pas a jour si c'est déjà  bon
  159.    delay(2);
  160.    outb(ctl, CONTROLREG);
  161.    delay(2);
  162.    
  163.  }
  164.  // 2) Mise de la valeur dans le registre data
  165.  outb(c, DATAREG); /* ecriture de l'octet avec pause jusqu'a achévement*/
  166.  delay(2);
  167.  // si outb_p ne plante pas
  168.  // 3) envoi d'un strobe pour signaler au LCD une commande
  169.  ctl &= 0xFE; // registre strobe mis a 0 => signal strobe haut en sortie
  170.  outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  171.  delay(2);
  172.  delay(2);
  173.  ctl |= 0x01; // registre strobe mis a 1 => signal strobe bas en sortie
  174.  outb(ctl, CONTROLREG); /* écriture du registre de controle avec cette valeur */
  175.  delay(2);
  176.  delay(2);
  177. }
  178.  
  179.  
  180. // On écrit une chaine
  181. void LCD_WriteString(char *s) {
  182.  unsigned char oldctl, ctl;
  183.  // 1) Mise a jour du registre des valeurs des pins de controle si necessaire
  184.  oldctl = ctl = inb(CONTROLREG);
  185.  ctl &= 0xD0;  // Bits du haut: direction mise à  0 (écriture) et bits du bas à  0
  186.  ctl |= 0x03;  // On force le bas à  0011 ce qui va mettre RS a 1 en sortie pour les valeurs de controle
  187.  if (oldctl != ctl) { // on met pas a jour si c'est déjà  bon
  188.    delay(2);
  189.    outb(ctl, CONTROLREG);
  190.    delay(2);
  191.    delay(2);
  192.  }
  193.  while (*s) {
  194.    // Mise du caractère dans le registre data
  195.    outb(*s, DATAREG);
  196.    delay(2);
  197.    // si outb_p ne plante pas
  198.    // 3) envoi d'un strobe pour signaler au LCD une commande
  199.    ctl &= 0xFE;
  200.    outb(ctl, CONTROLREG);
  201.    delay(2);
  202.    delay(2);
  203.    ctl |= 0x01;
  204.  
  205.    outb(ctl, CONTROLREG);
  206.    delay(2);
  207.    delay(2);
  208.    s++;
  209.  }
  210. }
  211.  
  212. // 0001xxxx -> LCD CursorMove (et Display Move)
  213. // 001xxxxx -> LCD Mode
  214. void LCD_Mode(int size8, int line2, int bigfont) {
  215.  unsigned char command = 0x20;  // Mode command
  216.  if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  217.  if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  218.  if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  219.  data_write(command);
  220.  delay(2);
  221.  delay(2);
  222. }
  223.  
  224. // Configuration initiale
  225. void LCD_SoftReset() {
  226.  // D'abord, 3 LCD_Mode avec la valeur correcte pour bit8
  227.  LCD_Mode(1,1,0); // Mode 8 bits data, 2 lines, 5x8 font
  228.  delay(5);
  229.  LCD_Mode(1,1,0); // Mode 8 bits data, 2 lines, 5x8 font
  230.  delay(2);
  231.  LCD_Mode(1,1,0); // Mode 8 bits data, 2 lines, 5x8 font
  232.  delay(2);
  233.  // Maintenant les parametres seront pris en compte
  234.  LCD_Mode(1,1,0); // Mode 8 bits data, 2 lines, 5x8 font
  235.  // les valeurs qui viennent d'être passé seront inchangeables dorénavant
  236.  LCD_Display(0, 0, 0); // Display Off
  237.  LCD_Clear(); // Display Clear
  238.  LCD_EntryMode(1, 0); // Left-Right, no shift
  239.  // Fin de la séquence de reset soft
  240. }
  241. int main (int argc, char * argv[]) {
  242.  unsigned char ctl;
  243.  if (ioperm(BASEPORT, 3, 1)) {
  244.    perror("can't set IO permissions!" );
  245.    return -1;
  246.  }
  247.  ctl = init_port();
  248.  sleep(5);
  249.  // Par défaut le hard reset de mise sous tension fait comme si on avait fait un SoftReset  
  250.  // avec les parametres suivants en fin de séquence:
  251.  // LCD_Mode(1,1,0);
  252.  // LCD_Display(0, 0, 0);  
  253.  // LCD_EntryMode(1, 0);
  254.  // Décommenter la ligne suivante si tu veux être en mode 2 lignes
  255.  //* LCD_SoftReset(); */
  256.  // A ce stade, on est prêt a utiliser le LCD
  257.  LCD_Display(1, 1, 1); // Display On LCD ON Cursor ON Cursor Blink
  258.  sleep(10);
  259.  // On peut afficher du texte
  260.  LCD_WriteString("Bonjour le monde ! " );
  261.  
  262.  getchar();
  263.  
  264.  restore_port(ctl);
  265.  if (ioperm(BASEPORT, 3, 0)) {
  266.    perror("can't reset IO permissions!" );
  267.    return -1;
  268.  }
  269.  return 0;
  270. }


 
Et sur pastebin ::= paralcd.c

Message cité 1 fois
Message édité par Profil supprimé le 01-11-2011 à 16:08:41
n°2109079
Profil sup​primé
Posté le 01-11-2011 à 17:12:08  answer
 

Si j'envoie "0123456789" j'ai "01676767xx '+ blink_curs avec des caractère bisarre en place des 'x'. mais c'est 8 et 9 mais il sont pourrit puis c'est décalé.
 
Je pense vraiment que les deux afficheur soit mortifié.
Mais y en a un que j'ai bien soudé et il semble encore plus mortifié.


Message édité par Profil supprimé le 01-11-2011 à 17:12:33
n°2109090
Profil sup​primé
Posté le 01-11-2011 à 17:48:31  answer
 

Arf, LCD_WriteString, écrit la chaîne et efface aussi tôt.  :love:  
Et j'ai pratiquement touché à rien.  :/
Faut faire pas mal de truc pour effacer soft. C'est bizarre.  :D  
Demain commande de nouveau LCD. Dans trois jour réception, soudure et retest.  :p  
 

n°2109138
Profil sup​primé
Posté le 01-11-2011 à 20:11:07  answer
 

Pour le texte qu'était pas le bon, c'était les soudures.
 
Ca affiche
 
 

Bonjour.............
Le monde !


 
 
Bravo Gilou, merci, merci encore ! [:powa]
 
L'écran est un poil mort mais ça fonctionne.

Message cité 1 fois
Message édité par Profil supprimé le 01-11-2011 à 20:11:34
n°2109153
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 21:53:06  profilanswer
 

[:wark0]  
 
 
Bon ben maintenant que ça marche, on va essayer un code propre et efficace:
 
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/io.h>
  5. // Base port cablé sur LPT1 ici
  6. #define BASEPORT    0x378
  7. #define DATAREG     BASEPORT+0
  8. #define STATUSREG   BASEPORT+1
  9. #define CONTROLREG  BASEPORT+2
  10. /* ***************************************************************************** */
  11. /*                       Commandes de bas niveau                                 */
  12. /* ***************************************************************************** */
  13. // Envoi de commandes SPP -> LCD
  14. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  15.     outb(cmd, DATAREG);        // Set command in DATA
  16.     outb(0x0A,    CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  17.     usleep(1);                 // Strobe duration: 500 ns  
  18.     outb(0x0B,    CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  19.     usleep(1);                 // Wait before next strobe: 500 ns
  20. }
  21. // Envoi d'un caractere SPP -> LCD
  22. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  23.     outb(c,    DATAREG);    // Set command in DATA
  24.     outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  25.     usleep(1);              // Strobe duration: 500 ns  
  26.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  27.     usleep(1);              // Wait before next strobe: 500 ns
  28. }
  29. // Lecture addresse courante RAM LCD -> SPP
  30. unsigned char address_read { // Cas RS=0, (Reception et) RW = 1
  31.     unsigned char address = 0x7F; // Mask for D6..D0
  32.    
  33.     outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  34.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  35.     usleep(1);              // Strobe duration: 500 ns
  36.     address &= inb(DATAREG);
  37.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  38.     usleep(1);              // Wait before next strobe: 500 ns
  39.     return address;
  40. }
  41. // Test du flag busy du LCD.  
  42. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  43.     unsigned char busy = 0x80; // Mask for D7
  44.    
  45.     outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  46.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Read, 8: RW E active]
  47.     usleep(1);              // Strobe duration: 500 ns
  48.     busy &= inb(DATAREG);
  49.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  50.     usleep(1);              // Wait before next strobe: 500 ns
  51.     return (busy?1:0);
  52. }
  53. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  54. unsigned char data_read {   // Cas RS=1, (Reception et) RW = 1
  55.     unsigned char data;
  56.    
  57.     outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  58.     outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Read, 0: RS RW E active]
  59.     usleep(1);              // Strobe duration: 500 ns  
  60.     data = inb(DATAREG);
  61.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  62.     usleep(1);              // Wait before next strobe: 500 ns
  63.     return data;
  64. }
  65. /* ***************************************************************************** */
  66. /*                       Commandes du LCD                                        */
  67. /* ***************************************************************************** */
  68. // cas 00000001
  69. void LCD_Clear() {
  70.     unsigned char command = 0x01;  // Clear command
  71.     send_cmd(command);
  72.     while (is_busy()) /* wait */;
  73. }
  74. // cas 0000001x
  75. void LCD_Home() {
  76.     unsigned char command = 0x02;  // Home command
  77.     send_cmd(command);
  78.     while (is_busy()) /* wait */;
  79. }
  80. // cas 000001xx
  81. void LCD_EntryMode(int lr, int shift) {
  82.     unsigned char command = 0x04;  // Entry Mode command
  83.     if (lr)      command |= 0x02; // Left -> Right [else Right Left] default
  84.     if (shift)   command |= 0x01; // Shift visible  
  85.     send_cmd(command);
  86.     while (is_busy()) /* wait */;
  87. }
  88. // cas 00001xxx
  89. void LCD_Display(int on, int cursor, int blink) {
  90.     unsigned char command = 0x08;  // DISPLAY command
  91.     if (on)      command |= 0x04; // Display on/off bit
  92.     if (cursor)  command |= 0x02; // Cursor on/off bit
  93.     if (blink)   command |= 0x01; // Cursor blink on/off bit
  94.     send_cmd(command);
  95.     while (is_busy()) /* wait */;
  96. }
  97. // cas 0001xxxx -> LCD CursorMove (et Display Move)
  98. // cas 001xxxxx
  99. void LCD_Mode(int size8, int line2, int bigfont) {
  100.     unsigned char command = 0x20;  // Mode command
  101.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  102.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  103.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  104.     send_cmd(command);
  105.     while (is_busy()) /* wait */;
  106. }
  107. // cas 01xxxxxx -> LCD Set CGRAM
  108. // cas 1xxxxxxx -> LCD Set DDRAM
  109. /* ***************************************************************************** */
  110. /*                       Fonctions de "haut niveau"                              */
  111. /* ***************************************************************************** */
  112. // Ecriture d'un caractère
  113. void LCD_WriteChar(char c) {
  114.     send_char(c);
  115.     while (is_busy()) /* wait */;
  116. }
  117. // Ecriture d'une chaine
  118. void LCD_WriteString(char *s) {
  119.     while (*s) {
  120. send_char(*s++);
  121. while (is_busy()) /* wait */;
  122.     }
  123. }
  124. // Reset du LCD et Initialisation
  125. // Note le hard reset de mise sous tension equivaut a LCD_SoftReset(1,0,0)
  126. void LCD_SoftReset(int size8, int line2, int bigfont) {
  127.     unsigned char command = 0x20;  // Mode command
  128.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  129.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  130.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  131.     // Sequence de reinitialisation
  132.     // D'abord, 3 commandes Mode avec la valeur voulue pour bit8
  133.     send_cmd(command); //  
  134.     usleep(5000);      // more than 4.1 ms
  135.     send_cmd(command);
  136.     usleep(500);      // more than 100 µs
  137.     send_cmd(command); // Maintenant is_busy va fonctionner
  138.     while (is_busy()) /* wait */;   
  139.    
  140.     // Sequence de parametrage
  141.     LCD_Mode(size8, line2, bigfont); // les valeurs passees seront inchangeables dorenavant
  142.     LCD_Display(0, 0, 0);            // Display Off
  143.     LCD_Clear();                     // Display Clear
  144.     LCD_EntryMode(1, 0);             // Left-Right, no shift
  145. }
  146. int main (int argc, char * argv[]) {
  147.     if (ioperm(BASEPORT, 3, 1)) {
  148. perror("can't set IO permissions!" );
  149. return -1;
  150.     }
  151.     sleep(1); // Temps necessaire a l'initialisation hard du LCD
  152.     // while (is_busy()) /* wait */; // Ce serait bien de tester ceci à la place du sleep(1)
  153.     // LCD_SoftReset(1,1,0); // Ce serait bien de tester ceci aussi
  154.     LCD_Display(1, 1, 1); // Display On LCD ON Cursor ON Cursor Blink
  155.     // On peut afficher du texte
  156.     LCD_WriteString("Bonjour le monde ! " );
  157.     printf("Taper quelque chose pour quitter le programme\n" );
  158.     getchar();
  159.     if (ioperm(BASEPORT, 3, 0)) {
  160. perror("can't reset IO permissions!" );
  161. return -1;
  162.     }
  163.     return 0;
  164. }


 
Pastebin: http://pastebin.com/ucy4LLfs
 
A mes fautes de frappe près, ça devrait marcher et être bien plus clair et efficace.
 
A+,

Message cité 1 fois
Message édité par gilou le 01-11-2011 à 22:24:27

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109154
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 22:06:08  profilanswer
 

Commentaires:
J'ai viré tous les delais inutiles. En fait, l'écriture sur un port est quasi instantanée (de l'ordre de la micro seconde (ou moins?), il y'a même du code hardware linux qui écrit en boucle un truc inutile sur un port comme boucle de temporisation de qques microsecondes).
Les délais utiles sont ceux du strobe:
500 micro secondes entre deux changements 0-> 1 ou 1 -> 0
EDIT: Je viens de relire la doc constructeur. c'est 500 nano secondes! Donc il faudrait changer mes usleep(500) par des usleep(1) dans le code précédent. JHe vais le changer ici, mais pas sur pastebin.
 
J'ai écrit une fonction courte pour chaque cas de figure en lecture/écriture du // au LCD , avec les valeurs câblées.
Comme l'écriture sur un port ne coûte rien, j'ai viré les tests pour ne pas réécrire, car si ça se trouve, le test prenait plus de temps.
 
Bref, ça devrait pulser.
 
J'ai viré init_port et release_port, car en y réfléchissant, c'était pas vraiment utile (ou en tout cas, ça se discute).
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109164
Profil sup​primé
Posté le 01-11-2011 à 22:53:09  answer
 

Yep, à par le address_read et data read auxquels j'ai ajouté (void) en paramètre si non ça compilait pas, ça compile.
Ca à l'air d'initialiser, mais pas de chaîne "Bonjour le monde !" et j'ai beau entrer un caractère, ça termine pas, ça doit être planté dans la boucle busy, "Ca recommence"  [:dmnl]

n°2109167
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 23:13:00  profilanswer
 

Mais tu arrives à "Taper quelque chose pour quitter le programme?"
Parce que si oui, les tests sur busy sont déjà effectués à ce stade.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109169
Profil sup​primé
Posté le 01-11-2011 à 23:14:24  answer
 

gilou a écrit :

Mais tu arrives à "Taper quelque chose pour quitter le programme?"
Parce que si oui, les tests sur busy sont déjà effectués à ce stade.
A+,


 
Non, en fait non, ça plante dans le busy de LCD_Display

n°2109170
Profil sup​primé
Posté le 01-11-2011 à 23:19:23  answer
 

un petit commentaire dans is_busy.

//outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]


 
Et ça roule


Message édité par Profil supprimé le 01-11-2011 à 23:22:26
n°2109171
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 23:23:19  profilanswer
 

Rhaa! Je viens de voir ton commentaire! :) :) :)
 
Bon ben si ça marche en virant cette ligne, il faut aussi la virer dans ses deux fonctions soeurs (address_read et data_read).
 
Bon ben à ce stade, tout est OK, et le code est a peu près aussi efficace qu'on puisse espérer en C
 
Je tacherais de rajouter les quelques commandes LCD qui manquent.
 
A+,


Message édité par gilou le 01-11-2011 à 23:27:33

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109173
Profil sup​primé
Posté le 01-11-2011 à 23:35:01  answer
 

A+ Gilou  :o  
 
Le LCD_SoftReset plante.
 
J'investis et je te tiens au courant ...

n°2109175
gilou
Modérateur
Modzilla
Posté le 01-11-2011 à 23:52:20  profilanswer
 

Ben j'ai juste suivi la doc quand à la séquence d'instruction constructeur

Code :
  1. send_cmd(command); //   
  2.     usleep(5000);      // more than 4.1 ms
  3.     send_cmd(command);
  4.     usleep(500);      // more than 100 µs  
  5.     send_cmd(command); // Maintenant is_busy va fonctionner
  6.     usleep(500);      //  Peut être un peu de délai en rab avant de tester busy
  7.     while (is_busy()) /* wait */;   // peut être le remplacer contre un délai long (usleep(5000); par exemple)
  8.  
  9.     // Sequence de parametrage
  10.     LCD_Mode(size8, line2, bigfont); // les valeurs passees seront inchangeables dorenavant
  11.     LCD_Display(0, 0, 0);            // Display Off
  12.     LCD_Clear();                     // Display Clear  // Peut être mettre ceci avant LCD_Mode(size8, line2, bigfont); car dans le reset hard, c'est en premier
  13.     LCD_EntryMode(1, 0);             // Left-Right, no shift


 
A+,


Message édité par gilou le 01-11-2011 à 23:53:29

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109176
Profil sup​primé
Posté le 02-11-2011 à 01:04:17  answer
 

Arf, ça m'avait affiché clair et net "Bonjour le monde ! " Comme si mon afficheur était réparé et pi j'y arrive plus.
C'est sensible au délais. (tu le savais ! )
 
Là, ça affiche Bonjour sans la barre du B le avec un l bizarre, monde : avec des consonne bizarre.
C'est l'affichage normale à priori, sauf que tout a l'heure, en fin de programme, j'ai tout mis à zéro à la main et c'était en clair. j'avais fait un perfect. Pi ça marche plus.
 
Faut que je prenne le datasheet, pour voir ce que je dois faire.
 
Et j'avais cru comprendre qu'il fallait envoyer E puis la donnée, puis abaisser E et la t'envoie la donnée et le lève E pour l'abaisser après. Mais peut-être je comprend pas le datasheet.


Message édité par Profil supprimé le 02-11-2011 à 01:05:44
n°2109178
gilou
Modérateur
Modzilla
Posté le 02-11-2011 à 01:35:03  profilanswer
 

Non non, si tu vas voir le programme en assembleur PIC, la séquence est la suivante:
On positionne les flags RW et RS du registre de controle (plus le flag de sens pour un port //)
On positionne les données dans le registre de données
Et on envoie alors un créneau. Le créneau n'est envoyé que quand tout est OK au niveau du controle et données, et ces valeurs doivent rester stables jusqu'a la fin du créneau.
 
Par contre, et c'est pas con, ils checkent le flag busy avant tout envoi d'instruction, plutôt qu'après.
Je vais faire comme eux.
 
A+,


Message édité par gilou le 02-11-2011 à 01:35:38

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109179
Profil sup​primé
Posté le 02-11-2011 à 01:59:12  answer
 

J'attends ton code.
Le miens fonctionne presque. J'ai un doute sur l'état de l'afficheur tout de même.
 
Là j'ai mis "paralcd version 2" en chaîne à afficher ; après une mise à zéro des deux registre, il faut patienter un instant, puis on peut lancer paralcd. Alors, la chaîne est écrite, mais le premier mot n'est pas lisible ; Il faut encore mettre à zero les registre et la le texte entier apparaît.
 
Ca jette.  :sol:  
 

n°2109180
gilou
Modérateur
Modzilla
Posté le 02-11-2011 à 02:28:37  profilanswer
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/io.h>
  5. // Base port cablé sur LPT1 ici
  6. #define BASEPORT    0x378
  7. #define DATAREG     BASEPORT+0
  8. #define STATUSREG   BASEPORT+1
  9. #define CONTROLREG  BASEPORT+2
  10. #define NEWCODE 1
  11. #ifdef NEWCODE
  12. /* ***************************************************************************** */
  13. /*                       Commandes de bas niveau                                 */
  14. /* ***************************************************************************** */
  15. // Envoi de commandes SPP -> LCD
  16. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  17.    
  18.     outb(0x0B, CONTROLREG); // Set Control [0x0B 0: Emission, B: RS RW E inactive]
  19.     outb(cmd,  DATAREG);    // Set command in DATA
  20.     outb(0x0A, CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  21.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  22. }
  23. // Envoi d'un caractere SPP -> LCD
  24. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  25.     outb(0x03, CONTROLREG); // Set Control [0x03 0: Emission, 3: RS active]
  26.     outb(c,    DATAREG);    // Set command in DATA
  27.     outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  28.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  29. }
  30. // Lecture busy + addresse courante RAM LCD -> SPP
  31. unsigned char address_read() { // Cas RS=0, (Reception et) RW = 1
  32.     unsigned char address = 0x7F; // Mask for D6..D0
  33.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  34.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  35.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  36.     address &= inb(DATAREG);
  37.     return address;
  38. }
  39. // Test du flag busy du LCD.  
  40. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  41.     unsigned char busy = 0x80; // Mask for D7
  42.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  43.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  44.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  45.     busy &= inb(DATAREG);
  46.     return (busy?1:0);
  47. }
  48. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  49. unsigned char data_read() {   // Cas RS=1, (Reception et) RW = 1
  50.     unsigned char data;
  51.     outb(0x21, CONTROLREG); // Set Control [0x21 2: Reception, 1: RS RW active]
  52.     outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Reception, 0: RS RW E active]
  53.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  54.     data = inb(DATAREG);
  55.     return data;
  56. }
  57. #else
  58. // Envoi de commandes SPP -> LCD
  59. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  60.     outb(cmd, DATAREG);        // Set command in DATA
  61.     outb(0x0A,    CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  62.     usleep(1);                 // Strobe duration: 500 ns   
  63.     outb(0x0B,    CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  64.     usleep(1);                 // Wait before next strobe: 500 ns
  65. }
  66. // Envoi d'un caractere SPP -> LCD
  67. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  68.     outb(c,    DATAREG);    // Set command in DATA
  69.     outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  70.     usleep(1);              // Strobe duration: 500 ns   
  71.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  72.     usleep(1);              // Wait before next strobe: 500 ns
  73. }
  74. // Lecture addresse courante RAM LCD -> SPP
  75. unsigned char address_read { // Cas RS=0, (Reception et) RW = 1
  76.     unsigned char address = 0x7F; // Mask for D6..D0
  77.  
  78.     outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  79.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  80.     usleep(1);              // Strobe duration: 500 ns
  81.     address &= inb(DATAREG);
  82.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  83.     usleep(1);              // Wait before next strobe: 500 ns
  84.     return address;
  85. }
  86. // Test du flag busy du LCD.   
  87. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  88.     unsigned char busy = 0x80; // Mask for D7
  89.  
  90.     outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  91.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Read, 8: RW E active]
  92.     usleep(1);              // Strobe duration: 500 ns
  93.     busy &= inb(DATAREG);
  94.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  95.     usleep(1);              // Wait before next strobe: 500 ns
  96.     return (busy?1:0);
  97. }
  98. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  99. unsigned char data_read {   // Cas RS=1, (Reception et) RW = 1
  100.     unsigned char data;
  101.  
  102.     outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  103.     outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Read, 0: RS RW E active]
  104.     usleep(1);              // Strobe duration: 500 ns   
  105.     data = inb(DATAREG);
  106.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  107.     usleep(1);              // Wait before next strobe: 500 ns
  108.     return data;
  109. }
  110. #endif
  111. /* ***************************************************************************** */
  112. /*                       Commandes du LCD                                        */
  113. /* ***************************************************************************** */
  114. // cas 00000001
  115. void LCD_Clear() {
  116.     unsigned char command = 0x01;  // Clear command
  117.     while (is_busy()) /* wait */;
  118.     send_cmd(command);
  119. }
  120. // cas 0000001x
  121. void LCD_Home() {
  122.     unsigned char command = 0x02;  // Home command
  123.     while (is_busy()) /* wait */;
  124.     send_cmd(command);
  125. }
  126. // cas 000001xx
  127. void LCD_EntryMode(int lr, int shift) {
  128.     unsigned char command = 0x04;  // Entry Mode command
  129.     if (lr)      command |= 0x02; // Left -> Right [else Right Left] default
  130.     if (shift)   command |= 0x01; // Shift visible  
  131.     while (is_busy()) /* wait */;
  132.     send_cmd(command);
  133. }
  134. // cas 00001xxx
  135. void LCD_Display(int on, int cursor, int blink) {
  136.     unsigned char command = 0x08;  // DISPLAY command
  137.     if (on)      command |= 0x04; // Display on/off bit
  138.     if (cursor)  command |= 0x02; // Cursor on/off bit
  139.     if (blink)   command |= 0x01; // Cursor blink on/off bit
  140.     while (is_busy()) /* wait */;
  141.     send_cmd(command);
  142. }
  143. // cas 0001xxxx -> LCD CursorMove (et Display Move)
  144. // cas 001xxxxx
  145. void LCD_Mode(int size8, int line2, int bigfont) {
  146.     unsigned char command = 0x20;  // Mode command
  147.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  148.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  149.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  150.     while (is_busy()) /* wait */;
  151.     send_cmd(command);
  152. }
  153. // cas 01xxxxxx -> LCD Set CGRAM
  154. // cas 1xxxxxxx -> LCD Set DDRAM
  155. /* ***************************************************************************** */
  156. /*                       Fonctions de "haut niveau"                              */
  157. /* ***************************************************************************** */
  158. // Ecriture d'un caractère
  159. void LCD_WriteChar(char c) {
  160.     while (is_busy()) /* wait */;
  161.     send_char(c);
  162. }
  163. // Ecriture d'une chaine
  164. void LCD_WriteString(char *s) {
  165.     while (*s) {
  166. while (is_busy()) /* wait */;
  167. send_char(*s++);
  168.     }
  169. }
  170. // Reset du LCD et Initialisation
  171. // Note le hard reset de mise sous tension equivaut a LCD_SoftReset(1,0,0)
  172. void LCD_SoftReset(int size8, int line2, int bigfont) {
  173.     unsigned char command = 0x20;  // Mode command
  174.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  175.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  176.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  177.     // Sequence de reinitialisation
  178.     // D'abord, 3 commandes Mode avec la valeur voulue pour bit8
  179.     while (is_busy()) /* wait */// is_busy inutilisable ensuite
  180.     send_cmd(command); //  
  181.     usleep(5000);      // more than 4.1 ms
  182.     send_cmd(command);
  183.     usleep(500);      // more than 100 µs
  184.     send_cmd(command); // Maintenant is_busy va fonctionner  
  185.    
  186.     // Sequence de parametrage
  187.     LCD_Mode(size8, line2, bigfont); // les valeurs passees seront inchangeables dorenavant
  188.     LCD_Display(0, 0, 0);            // Display Off
  189.     LCD_Clear();                     // Display Clear
  190.     LCD_EntryMode(1, 0);             // Left-Right, no shift
  191. }
  192. int main (int argc, char * argv[]) {
  193.     if (ioperm(BASEPORT, 3, 1)) {
  194. perror("can't set IO permissions!" );
  195. return -1;
  196.     }
  197.     // Attente de fin de l'initialisation hardware le cas échéant
  198.    
  199.     // LCD_SoftReset(1,1,0); // Ce serait bien de tester ceci aussi
  200.     LCD_Display(1, 1, 1); // Display On LCD ON Cursor ON Cursor Blink
  201.     // On peut afficher du texte
  202.     LCD_WriteString("Bonjour le monde ! " );
  203.     printf("Taper quelque chose pour quitter le programme\n" );
  204.     getchar();
  205.     if (ioperm(BASEPORT, 3, 0)) {
  206. perror("can't reset IO permissions!" );
  207. return -1;
  208.     }
  209.     return 0;
  210. }


 
 
 
 
Il y a deux modifs:
1) les is_busy() testés avant commande et non après
2) Les bonnes séquences pour les fonctions de bas niveau:
    Au vu du code assembleur, c'est
    1) Mise a jour du registre de controle, sans Bit E
    2) Si écriture, ecriture du registre data
    3) Mise a jour du registre de controle, avec Bit E
    4) Raz du registre de controle
    5) Si lecture, lecture du registre data
 
Si ces fonctions de bas niveau foiraient (j'ai viré toute temporisation, il y en a pas a ce niveau dans le code assembleur. Si ça déconne, je collerais un usleep(1) après chaque outb et basta), remettre les anciennes fonctions de bas niveau à la place en changeant #define NEWCODE 1 par #define NEWCODE 0
 
A+,


Message édité par gilou le 02-11-2011 à 02:33:00

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109181
gilou
Modérateur
Modzilla
Posté le 02-11-2011 à 02:53:11  profilanswer
 

Bon, si mon nouveau code a fonctionné, alors j'en ai un avec une boucle d'attente sur busy un peu plus perfectionnée:
 
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/io.h>
  5. // Base port cablé sur LPT1 ici
  6. #define BASEPORT    0x378
  7. #define DATAREG     BASEPORT+0
  8. #define STATUSREG   BASEPORT+1
  9. #define CONTROLREG  BASEPORT+2
  10. /* ***************************************************************************** */
  11. /*                       Commandes de bas niveau                                 */
  12. /* ***************************************************************************** */
  13. // Envoi de commandes SPP -> LCD
  14. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  15.    
  16.     outb(0x0B, CONTROLREG); // Set Control [0x0B 0: Emission, B: RS RW E inactive]
  17.     outb(cmd,  DATAREG);    // Set command in DATA
  18.     outb(0x0A, CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  19.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  20. }
  21. // Envoi d'un caractere SPP -> LCD
  22. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  23.     outb(0x03, CONTROLREG); // Set Control [0x03 0: Emission, 3: RS active]
  24.     outb(c,    DATAREG);    // Set command in DATA
  25.     outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  26.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  27. }
  28. // Lecture busy + addresse courante RAM LCD -> SPP
  29. unsigned char address_read() { // Cas RS=0, (Reception et) RW = 1
  30.     unsigned char address = 0x7F; // Mask for D6..D0
  31.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  32.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  33.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  34.     address &= inb(DATAREG);
  35.     return address;
  36. }
  37. // Test du flag busy du LCD.  
  38. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  39.     unsigned char busy = 0x80; // Mask for D7
  40.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  41.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  42.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  43.     busy &= inb(DATAREG);
  44.     return (busy?1:0);
  45. }
  46. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  47. unsigned char data_read() {   // Cas RS=1, (Reception et) RW = 1
  48.     unsigned char data;
  49.     outb(0x21, CONTROLREG); // Set Control [0x21 2: Reception, 1: RS RW active]
  50.     outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Reception, 0: RS RW E active]
  51.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  52.     data = inb(DATAREG);
  53.     return data;
  54. }
  55. void busy_wait() { // Cas RS=0, (Reception et) RW = 1
  56.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  57.     // Strobe loop
  58.     do {
  59. outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  60. outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  61.     }
  62.     while(0x80 & inb(DATAREG));
  63.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  64. }
  65. /* ***************************************************************************** */
  66. /*                       Commandes du LCD                                        */
  67. /* ***************************************************************************** */
  68. // cas 00000001
  69. void LCD_Clear() {
  70.     unsigned char command = 0x01;  // Clear command
  71.     busy_wait();
  72.     send_cmd(command);
  73. }
  74. // cas 0000001x
  75. void LCD_Home() {
  76.     unsigned char command = 0x02;  // Home command
  77.     busy_wait();
  78.     send_cmd(command);
  79. }
  80. // cas 000001xx
  81. void LCD_EntryMode(int lr, int shift) {
  82.     unsigned char command = 0x04;  // Entry Mode command
  83.     if (lr)      command |= 0x02; // Left -> Right [else Right Left] default
  84.     if (shift)   command |= 0x01; // Shift visible  
  85.     busy_wait();
  86.     send_cmd(command);
  87. }
  88. // cas 00001xxx
  89. void LCD_Display(int on, int cursor, int blink) {
  90.     unsigned char command = 0x08;  // DISPLAY command
  91.     if (on)      command |= 0x04; // Display on/off bit
  92.     if (cursor)  command |= 0x02; // Cursor on/off bit
  93.     if (blink)   command |= 0x01; // Cursor blink on/off bit
  94.     busy_wait();
  95.     send_cmd(command);
  96. }
  97. // cas 0001xxxx -> LCD CursorMove (et Display Move)
  98. // cas 001xxxxx
  99. void LCD_Mode(int size8, int line2, int bigfont) {
  100.     unsigned char command = 0x20;  // Mode command
  101.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  102.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  103.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  104.     busy_wait();
  105.     send_cmd(command);
  106. }
  107. // cas 01xxxxxx -> LCD Set CGRAM
  108. // cas 1xxxxxxx -> LCD Set DDRAM
  109. /* ***************************************************************************** */
  110. /*                       Fonctions de "haut niveau"                              */
  111. /* ***************************************************************************** */
  112. // Ecriture d'un caractère
  113. void LCD_WriteChar(char c) {
  114.     busy_wait();
  115.     send_char(c);
  116. }
  117. // Ecriture d'une chaine
  118. void LCD_WriteString(char *s) {
  119.     while (*s) {
  120. busy_wait();
  121. send_char(*s++);
  122.     }
  123. }
  124. // Reset du LCD et Initialisation
  125. // Note le hard reset de mise sous tension equivaut a LCD_SoftReset(1,0,0)
  126. void LCD_SoftReset(int size8, int line2, int bigfont) {
  127.     unsigned char command = 0x20;  // Mode command
  128.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  129.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  130.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  131.     // Sequence de reinitialisation
  132.     // D'abord, 3 commandes Mode avec la valeur voulue pour bit8
  133.     busy_wait();  // Le flag busy inutilisable ensuite
  134.     send_cmd(command); //  
  135.     usleep(5000);      // more than 4.1 ms
  136.     send_cmd(command);
  137.     usleep(500);      // more than 100 µs
  138.     send_cmd(command); // Maintenant Le flag busy va fonctionner  
  139.    
  140.     // Sequence de parametrage
  141.     LCD_Mode(size8, line2, bigfont); // les valeurs passees seront inchangeables dorenavant
  142.     LCD_Display(0, 0, 0);            // Display Off
  143.     LCD_Clear();                     // Display Clear
  144.     LCD_EntryMode(1, 0);             // Left-Right, no shift
  145. }
  146. int main (int argc, char * argv[]) {
  147.     if (ioperm(BASEPORT, 3, 1)) {
  148. perror("can't set IO permissions!" );
  149. return -1;
  150.     }
  151.     // Attente de fin de l'initialisation hardware le cas échéant
  152.    
  153.     // LCD_SoftReset(1,1,0); // Ce serait bien de tester ceci aussi
  154.     LCD_Display(1, 1, 1); // Display On LCD ON Cursor ON Cursor Blink
  155.     // On peut afficher du texte
  156.     LCD_WriteString("Bonjour le monde ! " );
  157.     printf("Taper quelque chose pour quitter le programme\n" );
  158.     getchar();
  159.     if (ioperm(BASEPORT, 3, 0)) {
  160. perror("can't reset IO permissions!" );
  161. return -1;
  162.     }
  163.     return 0;
  164. }


 
Et sinon, tant pis, parce que je ne serais plus à portée d'un ordi avant demain soir.
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109182
Profil sup​primé
Posté le 02-11-2011 à 04:30:49  answer
 

Le premier code que tu viens de poster fonctionnerait, a priori parce que l'afficheur à pas l'air dans son état normal, comme ça :

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/io.h>
  5. // Base port cablé sur LPT1 ici
  6. #define BASEPORT    0x378
  7. #define DATAREG     BASEPORT+0
  8. #define STATUSREG   BASEPORT+1
  9. #define CONTROLREG  BASEPORT+2
  10. #define NEWCODE 1
  11. #ifdef NEWCODE
  12. /* ***************************************************************************** */
  13. /*                       Commandes de bas niveau                                 */
  14. /* ***************************************************************************** */
  15. // Envoi de commandes SPP -> LCD
  16. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  17.  
  18.  outb(0x0B, CONTROLREG); // Set Control [0x0B 0: Emission, B: RS RW E inactive]
  19.  usleep(100);
  20.  outb(cmd,  DATAREG);    // Set command in DATA
  21.  usleep(100);
  22.  outb(0x0A, CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  23.  usleep(100);
  24.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  25.  usleep(100);
  26. }
  27. // Envoi d'un caractere SPP -> LCD
  28. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  29.  outb(0x03, CONTROLREG); // Set Control [0x03 0: Emission, 3: RS active]
  30.  usleep(100);
  31.  outb(c,    DATAREG);    // Set command in DATA
  32.  usleep(100);
  33.  outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  34.  usleep(100);
  35.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  36.  usleep(100);
  37. }
  38. // Lecture busy + addresse courante RAM LCD -> SPP
  39. unsigned char address_read() { // Cas RS=0, (Reception et) RW = 1
  40.  unsigned char address = 0x7F; // Mask for D6..D0
  41.  outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  42.  usleep(1);
  43.  outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  44.  usleep(1);
  45.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  46.  usleep(1);
  47.  address &= inb(DATAREG);
  48.  return address;
  49. }
  50. // Test du flag busy du LCD.  
  51. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  52.  unsigned char busy = 0x80; // Mask for D7
  53.  outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  54.  usleep(100);
  55.  outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  56.  usleep(100);
  57.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  58.  usleep(100);
  59.  busy &= inb(DATAREG);
  60.  return (busy?1:0);
  61. }
  62. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  63. unsigned char data_read() {   // Cas RS=1, (Reception et) RW = 1
  64.  unsigned char data;
  65.  outb(0x21, CONTROLREG); // Set Control [0x21 2: Reception, 1: RS RW active]
  66.  usleep(1);
  67.  outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Reception, 0: RS RW E active]
  68.  usleep(1);
  69.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  70.  usleep(1);
  71.  data = inb(DATAREG);
  72.  return data;
  73. }
  74. #else
  75. // Envoi de commandes SPP -> LCD
  76. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  77.  outb(cmd, DATAREG);        // Set command in DATA
  78.  usleep(100);
  79.  outb(0x0A,    CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  80.  usleep(100);                 // Strobe duration: 500 ns  
  81.  outb(0x0B,    CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  82.  usleep(100);                 // Wait before next strobe: 500 ns
  83. }
  84. // Envoi d'un caractere SPP -> LCD
  85. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  86.  outb(c,    DATAREG);    // Set command in DATA
  87.  usleep(100);
  88.  outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  89.  usleep(100);              // Strobe duration: 500 ns  
  90.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  91.  usleep(100);              // Wait before next strobe: 500 ns
  92. }
  93. // Lecture addresse courante RAM LCD -> SPP
  94. unsigned char address_read { // Cas RS=0, (Reception et) RW = 1
  95.  unsigned char address = 0x7F; // Mask for D6..D0
  96.    
  97.  outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  98.  usleep(100);
  99.  outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  100.  usleep(100);              // Strobe duration: 500 ns
  101.  address &= inb(DATAREG);
  102.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  103.  usleep(100);              // Wait before next strobe: 500 ns
  104.  return address;
  105. }
  106. // Test du flag busy du LCD.  
  107. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  108.  unsigned char busy = 0x80; // Mask for D7
  109.  
  110.  outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  111.  usleep(100);
  112.  outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Read, 8: RW E active]
  113.  usleep(100);              // Strobe duration: 500 ns
  114.  busy &= inb(DATAREG);
  115.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  116.  usleep(100);              // Wait before next strobe: 500 ns
  117.  return (busy?1:0);
  118. }
  119. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  120. unsigned char data_read {   // Cas RS=1, (Reception et) RW = 1
  121.  unsigned char data;
  122.  
  123.  outb(0x00, DATAREG);    // reset DATA [NOTE: C'est peut être une précaution inutile, a tester sans ]
  124.  usleep(100);
  125.  outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Read, 0: RS RW E active]
  126.  usleep(100);              // Strobe duration: 500 ns  
  127.  data = inb(DATAREG);
  128.  outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Write, B: RS RW E inactive]
  129.  usleep(100);              // Wait before next strobe: 500 ns
  130.  return data;
  131. }
  132. #endif
  133. /* ***************************************************************************** */
  134. /*                       Commandes du LCD                                        */
  135. /* ***************************************************************************** */
  136. // cas 00000001
  137. void LCD_Clear() {
  138.  unsigned char command = 0x01;  // Clear command
  139.  while (is_busy()) /* wait */;
  140.  usleep(1);
  141.  send_cmd(command);
  142. }
  143. // cas 0000001x
  144. void LCD_Home() {
  145.  unsigned char command = 0x02;  // Home command
  146.  while (is_busy()) /* wait */;
  147.  send_cmd(command);
  148. }
  149. // cas 000001xx
  150. void LCD_EntryMode(int lr, int shift) {
  151.  unsigned char command = 0x04;  // Entry Mode command
  152.  if (lr)      command |= 0x02; // Left -> Right [else Right Left] default
  153.  if (shift)   command |= 0x01; // Shift visible  
  154.  while (is_busy()) /* wait */;
  155.  usleep(1);
  156.  send_cmd(command);
  157. }
  158. // cas 00001xxx
  159. void LCD_Display(int on, int cursor, int blink) {
  160.  unsigned char command = 0x08;  // DISPLAY command
  161.  if (on)      command |= 0x04; // Display on/off bit
  162.  if (cursor)  command |= 0x02; // Cursor on/off bit
  163.  if (blink)   command |= 0x01; // Cursor blink on/off bit
  164.  while (is_busy()) /* wait */;
  165.  usleep(1);
  166.  send_cmd(command);
  167. }
  168. // cas 0001xxxx -> LCD CursorMove (et Display Move)
  169. // cas 001xxxxx
  170. void LCD_Mode(int size8, int line2, int bigfont) {
  171.  unsigned char command = 0x20;  // Mode command
  172.  if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  173.  if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  174.  if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  175.  while (is_busy()) /* wait */;
  176.  send_cmd(command);
  177. }
  178. // cas 01xxxxxx -> LCD Set CGRAM
  179. // cas 1xxxxxxx -> LCD Set DDRAM
  180. /* ***************************************************************************** */
  181. /*                       Fonctions de "haut niveau"                              */
  182. /* ***************************************************************************** */
  183. // Ecriture d'un caractère
  184. void LCD_WriteChar(char c) {
  185.  while (is_busy()) /* wait */;
  186.  usleep(1);
  187.  send_char(c);
  188. }
  189. // Ecriture d'une chaine
  190. void LCD_WriteString(char *s) {
  191.  while (*s) {
  192.    while (is_busy()) /* wait */;
  193.    usleep(1);
  194.    send_char(*s++);
  195.  }
  196. }
  197. // Reset du LCD et Initialisation
  198. // Note le hard reset de mise sous tension equivaut a LCD_SoftReset(1,0,0)
  199. void LCD_SoftReset(int size8, int line2, int bigfont) {
  200.  unsigned char command = 0x20;  // Mode command
  201.  if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  202.  if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  203.  if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  204.  // Sequence de reinitialisation
  205.  // D'abord, 3 commandes Mode avec la valeur voulue pour bit8
  206.  while (is_busy()) /* wait */;  // is_busy inutilisable ensuite
  207.  send_cmd(command); //  
  208.  usleep(5000);      // more than 4.1 ms
  209.  send_cmd(command);
  210.  usleep(500);      // more than 100 µs
  211.  send_cmd(command); // Maintenant is_busy va fonctionner  
  212.  usleep(500);      // more than 100 µs
  213.  // Sequence de parametrage
  214.  LCD_Clear();                     // Display Clear
  215.  LCD_Mode(size8, line2, bigfont); // les valeurs passees seront inchangeables dorenavant
  216.  LCD_Display(0, 0, 0);            // Display Off
  217.    
  218.  LCD_EntryMode(1, 0);             // Left-Right, no shift
  219. }
  220. int main (int argc, char * argv[]) {
  221.  if (ioperm(BASEPORT, 3, 1)) {
  222.    perror("can't set IO permissions!" );
  223.    return -1;
  224.  }
  225.  // Attente de fin de l'initialisation hardware le cas échéant
  226.  
  227.  LCD_SoftReset(1,1,0); // Ce serait bien de tester ceci aussi
  228.  LCD_Display(1, 1, 1); // Display On LCD ON Cursor ON Cursor Blink
  229.  // On peut afficher du texte
  230.  LCD_WriteString("Bonjour le monde ! " );
  231.  printf("Taper quelque chose pour quitter le programme\n" );
  232.  getchar();
  233.  if (ioperm(BASEPORT, 3, 0)) {
  234.    perror("can't reset IO permissions!" );
  235.    return -1;
  236.  }
  237.  return 0;
  238. }


 
Le second, avec le busy avancé, j'ai apporté vite fait les même modif, soit l'ajout ou la modif de délais d'attente, ne fonctionne pas pour le moment.

n°2109183
Profil sup​primé
Posté le 02-11-2011 à 04:35:28  answer
 

gilou a écrit :

.../...
Et sinon, tant pis, parce que je ne serais plus à portée d'un ordi avant demain soir.
 
A+,
 


 
Ne me dis pas que tu as écrit tout ça en SMS style ?  :heink:   :D

n°2109184
gilou
Modérateur
Modzilla
Posté le 02-11-2011 à 05:01:14  profilanswer
 

Non non, je suis en dehors de chez moi jusqu'a demain soir.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2109185
Profil sup​primé
Posté le 02-11-2011 à 05:13:56  answer
 

Est-ce que dans ls deux dernier code que tu as posté, il n'y a que le busy qui soit modifier.
 
Si oui. ça fonctionne si non, faudra chercher.

n°2109186
gilou
Modérateur
Modzilla
Posté le 02-11-2011 à 05:22:00  profilanswer
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/io.h>
  5. // Base port cablé sur LPT1 ici
  6. #define BASEPORT    0x378
  7. #define DATAREG     BASEPORT+0
  8. #define STATUSREG   BASEPORT+1
  9. #define CONTROLREG  BASEPORT+2
  10. #define REGISTER_DELAY 1
  11. /* ***************************************************************************** */
  12. /*                       Commandes de bas niveau                                 */
  13. /* ***************************************************************************** */
  14. // Envoi de commandes SPP -> LCD
  15. void send_cmd(unsigned char cmd) { // Cas RS=0, (Emission et) RW=0
  16.    
  17.     outb(cmd,  DATAREG);    // Set command in DATA
  18.     outb(0x0B, CONTROLREG); // Set Control [0x0B 0: Emission, B: RS RW E inactive]
  19.     usleep(REGISTER_DELAY);
  20.     outb(0x0A, CONTROLREG); // Signal LCD with a strobe [0x0A 0: Emission, A: E active]
  21.     usleep(REGISTER_DELAY);
  22.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  23.     usleep(REGISTER_DELAY);
  24. }
  25. // Envoi d'un caractere SPP -> LCD
  26. void send_char(char c) {    // Cas RS=1, (Ecriture et) RW = 0
  27.     outb(c,    DATAREG);    // Set command in DATA
  28.     outb(0x03, CONTROLREG); // Set Control [0x03 0: Emission, 3: RS active]
  29.     usleep(REGISTER_DELAY);
  30.     outb(0x02, CONTROLREG); // Signal LCD with a strobe [0x02 0: Emission, 2: RS E active]
  31.     usleep(REGISTER_DELAY);
  32.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  33.     usleep(REGISTER_DELAY);
  34. }
  35. // Lecture busy + addresse courante RAM LCD -> SPP
  36. unsigned char address_read() { // Cas RS=0, (Reception et) RW = 1
  37.     unsigned char address = 0x7F; // Mask for D6..D0
  38.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  39.     usleep(REGISTER_DELAY);
  40.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  41.     usleep(REGISTER_DELAY);
  42.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  43.     usleep(REGISTER_DELAY);
  44.     address &= inb(DATAREG);
  45.     return address;
  46. }
  47. // Test du flag busy du LCD.  
  48. int is_busy() {             // Cas RS=0, (Reception et) RW = 1
  49.     unsigned char busy = 0x80; // Mask for D7
  50.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  51.     usleep(REGISTER_DELAY);
  52.     outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  53.     usleep(REGISTER_DELAY);
  54.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  55.     usleep(REGISTER_DELAY);
  56.     busy &= inb(DATAREG);
  57.     return (busy?1:0);
  58. }
  59. // Lecture valeur a l'addresse courante RAM LCD -> SPP
  60. unsigned char data_read() {   // Cas RS=1, (Reception et) RW = 1
  61.     unsigned char data;
  62.     outb(0x21, CONTROLREG); // Set Control [0x21 2: Reception, 1: RS RW active]
  63.     usleep(REGISTER_DELAY);
  64.     outb(0x20, CONTROLREG); // Signal LCD with a strobe [0x20 2: Reception, 0: RS RW E active]
  65.     usleep(REGISTER_DELAY);
  66.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  67.     usleep(REGISTER_DELAY);
  68.     data = inb(DATAREG);
  69.     return data;
  70. }
  71. void busy_wait() { // Cas RS=0, (Reception et) RW = 1
  72.     outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  73.     usleep(REGISTER_DELAY);
  74.     // Strobe loop
  75.     do {
  76. outb(0x28, CONTROLREG); // Signal LCD with a strobe [0x28 2: Reception, 8: RW E active]
  77. usleep(REGISTER_DELAY);
  78. outb(0x29, CONTROLREG); // Set Control [0x29 2: Reception, 9: RW active]
  79. usleep(REGISTER_DELAY);
  80.     }
  81.     while(0x80 & inb(DATAREG));
  82.     outb(0x0B, CONTROLREG); // Reset CONTROL [0x0B 0: Emission, B: RS RW E inactive]
  83.     usleep(REGISTER_DELAY);
  84. }
  85. /* ***************************************************************************** */
  86. /*                       Commandes du LCD                                        */
  87. /* ***************************************************************************** */
  88. // cas 00000001
  89. void LCD_Clear() {
  90.     unsigned char command = 0x01;  // Clear command
  91.     busy_wait();
  92.     send_cmd(command);
  93. }
  94. // cas 0000001x
  95. void LCD_Home() {
  96.     unsigned char command = 0x02;  // Home command
  97.     busy_wait();
  98.     send_cmd(command);
  99. }
  100. // cas 000001xx
  101. void LCD_EntryMode(int lr, int shift) {
  102.     unsigned char command = 0x04;  // Entry Mode command
  103.     if (lr)      command |= 0x02; // Left -> Right [else Right Left] default
  104.     if (shift)   command |= 0x01; // Shift visible  
  105.     busy_wait();
  106.     send_cmd(command);
  107. }
  108. // cas 00001xxx
  109. void LCD_Display(int on, int cursor, int blink) {
  110.     unsigned char command = 0x08;  // DISPLAY command
  111.     if (on)      command |= 0x04; // Display on/off bit
  112.     if (cursor)  command |= 0x02; // Cursor on/off bit
  113.     if (blink)   command |= 0x01; // Cursor blink on/off bit
  114.     busy_wait();
  115.     send_cmd(command);
  116. }
  117. // cas 0001xxxx -> LCD CursorMove (et Display Move)
  118. // cas 001xxxxx
  119. void LCD_Mode(int size8, int line2, int bigfont) {
  120.     unsigned char command = 0x20;  // Mode command
  121.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  122.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  123.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  124.     busy_wait();
  125.     send_cmd(command);
  126. }
  127. // cas 01xxxxxx -> LCD Set CGRAM
  128. // cas 1xxxxxxx -> LCD Set DDRAM
  129. /* ***************************************************************************** */
  130. /*                       Fonctions de "haut niveau"                              */
  131. /* ***************************************************************************** */
  132. // Ecriture d'un caractère
  133. void LCD_WriteChar(char c) {
  134.     busy_wait();
  135.     send_char(c);
  136. }
  137. // Ecriture d'une chaine
  138. void LCD_WriteString(char *s) {
  139.     while (*s) {
  140. busy_wait();
  141. send_char(*s++);
  142.     }
  143. }
  144. // Reset du LCD et Initialisation
  145. // Note le hard reset de mise sous tension equivaut a LCD_SoftReset(1,0,0)
  146. void LCD_SoftReset(int size8, int line2, int bigfont) {
  147.     unsigned char command = 0x20;  // Mode command
  148.     if (size8)   command |= 0x10; // 8 bit data [else 4 bit data mode] default
  149.     if (line2)   command |= 0x08; // 2 lines mode [else 1 line mode] default
  150.     if (bigfont) command |= 0x04; // 5x11 font [else 5x8 font, default]
  151.     // Sequence de reinitialisation
  152.     // D'abord, 3 commandes Mode avec la valeur voulue pour bit8
  153.     busy_wait();  // Le flag busy inutilisable ensuite
  154.     send_cmd(command); //  
  155.     usleep(5000);      // more than 4.1 ms
  156.     send_cmd(command);
  157.     usleep(500);      // more than 100 µs
  158.     send_cmd(command); // Maintenant Le flag busy va fonctionner  
  159.    
  160.     // Sequence de parametrage
  161.     LCD_Mode(size8, line2, bigfont); // les valeurs passees seront inchangeables dorenavant
  162.     LCD_Display(0, 0, 0);            // Display Off
  163.     LCD_Clear();                     // Display Clear
  164.     LCD_EntryMode(1, 0);             // Left-Right, no shift
  165. }
  166. int main (int argc, char * argv[]) {
  167.     if (ioperm(BASEPORT, 3, 1)) {
  168. perror("can't set IO permissions!" );
  169. return -1;
  170.     }
  171.     // Attente de fin de l'initialisation hardware le cas échéant
  172.    
  173.     // LCD_SoftReset(1,1,0); // Ce serait bien de tester ceci aussi
  174.     LCD_Display(1, 1, 1); // Display On LCD ON Cursor ON Cursor Blink
  175.     // On peut afficher du texte
  176.     LCD_WriteString("Bonjour le monde ! " );
  177.     printf("Taper quelque chose pour quitter le programme\n" );
  178.     getchar();
  179.     if (ioperm(BASEPORT, 3, 0)) {
  180. perror("can't reset IO permissions!" );
  181. return -1;
  182.     }
  183.     return 0;
  184. }


En jouant sur la valeur de REGISTER_DELAY on devrait finir par tomber sur une qui marche
 
Les changements de mes deux codes précédents:
1) Réécriture en deux phases dans le registre de contrôle, au lieu d'une seule, ça colle mieux avec le datasheet (sinon, le strobe risque de démarrer quand le voltage est pas assez haut sur RS ou RW)  
2) (code suivant)
    code avec busy_wait, au lieu de is_busy  (et donc juste une boucle de strobe-lecture)
Bon, ce coup ci, j’arrête la machine.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3  4  5  6  7  8

Aller à :
Ajouter une réponse
 

Sujets relatifs
[C] Modifier un tableau existant ... pour bouger un pion ![C# / .Net] Migration OS 32Bits vers OS 64Bits. Quid des Perfs?
[C#] FormView, edit/insert mode[C] programme cherche les racines des polynomes
[C] trouver la longueur de la plus longue suite decroissante en CC++, Compter des caractères ...
Linux C/C++ broadcast UDP sur machine sans gatewayConvolution de 2 tableaux unidimensionnels avec FFTW C++
Plus de sujets relatifs à : [ Divers / C ] Ecrire pour un afficheur LCD


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR