Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Commentez, partagez et proposez des Tutos en langage C !
Ecran LCD en I²C avec PCF2119
Jérémy
Administrateur du site
Administrateur du site
Messages : 2112
Âge : 39
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » sam. 12 sept. 2015 18:59

Bonjour à tous,

J'ai tellement galéré pour réussir à faire fonctionner cet écran , que je me devais de faire un petit tuto, pour partager mes erreurs et solutions si jamais quelqu'un tomberai sur les mêmes problématiques que moi.

Je n'ai pas la prétention de vous expliquer la communication l'I²C voici un excellent document très bien écrit :
Présentation de l'I2C avec un PIC
Je vous propose juste un programme qui fonctionne bien chez moi . Je remercie au passage Paulfjujo qui m'a quasiment fournit le code clef en main, et qui à su être patient pour m'aider .


Image

Configuration :

- PIC18F45K22
- IDE : MikroC Pro for PIC Version 6.6.2
- Compilateur : Mikro prog suite fo PIC V 2.32
- Plaque Easy PIC V7
- Utilisation des connecteurs MikroBus pour relier l'i²C






Attention!! Les pièges à éviter :

- Il faut mettre des Résistances de pull-Up sont les broches RC3 et RC4 ( SDA et SCL) de votre PIC, entre 4.7k et 10k feront l'affaire. Elles sont INDISPENSABLES pour établir la communication I²C.
- Vous devez aussi mettre les broches RC3 et RC4 en entrées grâce au registre TRIS. afin de les configurer en collecteur ouvert indispensable pour que le maitre prenne la communication.
- La configuration du contraste est primordiale, n'évitez pas cette étape.
- Vérifiez que que votre écran est actif avec le registre "display_ctl" il s'agit du bit2 de ce registre qui doit être à "1" pour l'activer.

Les conseils :

- Attention l'alimentation est en 3V et non en 5V.
- Soyez sûr et certain de l'Adresse I²C de votre équipement , sous peine de vous voir refaire toutes vos test ! Faire clignoté une LED pour vérifier votre adresse I²C, si elle clignote pas c'est que l'I²C est bloqué donc mauvaise adresse.
- Le compteur est un integer , donc sur 5 caractères ( int va de 0 à 65535), donc sur l’écran il faut réserver 5 caractères et faire attention pour que cela n'écrase pas du texte.

Code : Tout sélectionner

/*##################################################################################
##############################     Variable / Constante    ##########################
###################################################################################*/
#define LCD_ADR 0x74;         // Adresse de l'esclave I2C en constante
char ligne,colonne, position ; // Déclaration variable

unsigned int i,compteur;       // Variable
sbit LED_RA4 at LATA4_bit ;    // Déclaration de la led sur RA4

char *text;                    // Création d'un pointeur nommé text
char variable[6];             // Création du tableau pour stockage variable en string

void efface_ecran();           // Déclaration de la fonction pour effacer l'écran
void Display_init();           // Déclaration de la fonction pour initialiser l'écran
void  affiche_txt(char ligne, char colonne, char *text);// Déclaration de la fonction pour afficher le texte

/*##################################################################################
############################   PROGRAMME PRINCIPAL    ##############################
##################################################################################*/
void main ()
{
  TRISA = 0b11101111 ;    // RA4 en sortie  pour la led
  ANSELA=0;               // Configure le PORTA en digital
  LED_RA4 = 0 ;           // On éteint la LED

  TRISC = 0b11111111 ;    // ATTENTION en I²C les pattes SDA et SCL doivent être misent en entrée( collecteur ouvert)
  ANSELC = 0 ;            // Configure le PORTC en digital

  I2C1_Init(100000);      // Initialisation de l'I2C
  Delay_ms(100);          // Pause de 100 ms

  Display_init();        // Initialise et configure l'écran

  efface_ecran();        // Efface l'écran (remplit l'écran avec des blanks)

  affiche_txt (1,0,"Hello World !!!"); // Sur la 1 ligne, colonne 0 on écrit le texte
  affiche_txt (2,0,"Compteur : ");    // Sur la 2 ligne, colonne 0 on écrit le texte

  compteur = 0;          // Initialisation du compteur à 0

//##########################    BOUCLE INFINIE    ##################################
  while(1)
  {

    WordToStr (compteur, variable); // On transforme la variable en string pour affichage
    affiche_txt (2,11, variable);   // Sur la 2 ligne, colonne 12 on va affiché le compteur
    compteur = compteur++;          // On incrémente le compteur

   LED_RA4 = 1 ;                  // J'allume la LED pour vérifier que le programme tourne
   delay_ms (50);                 // Une marque une pause
   LED_RA4 = 0 ;                  // On éteint la LED
   delay_ms (50);                 // Une marque une pause
  }
}

/*##################################################################################
###########################    AFFICHAGE DU TEXTE    ###############################
##################################################################################*/
void  affiche_txt (char ligne, char colonne, char *text)   // Fonction avec paramètres d'entrées (voir tuto sur fonctions)
    {
        if (ligne==1) position = 0x80 + colonne;  // On détermine la position sur la ligne 1
        if (ligne==2) position = 0xC0 + colonne;  // On détermine la position sur la ligne 2

        I2C1_Start();                // Ouverture d'une Com I2C
        I2C1_Wr(LCD_ADR);            // Envoi de l'adresse esclave
        I2C1_Wr(0x00);               // Byte de contrôle pour envoyer une instruction
        I2C1_Wr(position);           // INSTRUC : position de l'ADDR du curseur 1ere ligne de 80 à 8F
        I2C1_Repeated_Start();       // Répétition de l'ouverture de la com I2C
        I2C1_Wr(LCD_ADR);            // Envoi de l'adresse esclave
        I2C1_Wr(0x40);               // Byte de contrôle pour envoyer une DATA

         i=0;                        // Raz de i
         while (  text[i] != '\0' )  // Temps qu'on est pas la fin du texte on continue
          {
            I2C1_Wr( 0x80 + text[i++] );    // Écriture de la lettre ou pointe le pointeur
          }

        Delay_ms(10);                      // Pause de 10ms
        I2C1_Stop();                        // Fin de l'I2C
      }


/*##################################################################################
#########################     INITIALISATION DE L’ÉCRAN    #########################
##################################################################################*/
void Display_init()
    {
        Delay_ms(500);        // Une marque une pause

        I2C1_Start();         // Ouverture de la com I²C

        I2C1_Wr(LCD_ADR);     // Adresse de l'esclave

        // CONTROL_Mode       // bit7 -> 0=last control byte, 1=another control byte
                              // bit6 -> 0=registre inst , 1=registre Data
        I2C1_Wr(0x00);        // bit5à0 -> 0
                              // 0b00000000 = 0x00

        // function_set       // bit7 à 5 valeurs fixes : 001
                              // bit4: 0:2x4bit, 1:8 bits
        I2C1_Wr(0x34);        // bit3: 0 Non utilisé
                              // bit2: 0: 1ligne/32char, 1: 2lignes/16char
                              // bit1: 0: 1/18 multiplex, 1: 1/9 multiplex
                              // bit0: 0: standard instr., 1: extended instr.
                              // 0b00110100 = 0x34

        // display_ctl        // bit7 à  valeur fixe : 00001
                              // bit2: 0:display off, 1:display On
        I2C1_Wr(0x0C);        // bit1: 0:cursor off, 1:cursor On
                              // bit0: 0:clignotement off, 1:On
                              // 0b00001100 = 0x0C

        // Entry_mode_set     // bit7à 2: valeur fixe : 000001
                              // bit1: 0:Décrémente l'adresse , 1:Incrémente (curseur vers la droite)
        I2C1_Wr(0x06);        // bit0: 0:No shift , 1: Shift display
                              // 0b00000110 = 0x06

        // Extended instructions
        I2C1_Wr(0x35);        // DL: 8 bits, M: 16 by two line, SL: 1:18, H: extended instruction set

        // Disp_config        // bit7à 2: valeur fixe : 000001
        I2C1_Wr(0x05);        // bit1 : 0=left to right, 1=Right to left
                              // bit0 : 0=top to bottom  1=bottom to t

        // VLCD_SET           // Réglage du contraste  ##### OBLIGATOIRE #######
                              // bit7 : valeur fixe : 1
        I2C1_Wr(0x98);        // bit6: 0=registre VA ; 1=registre VB
                              // bit5à 0: 000000 jusqu’à 111111 pour le contraste

        // Normal instruction
        I2C1_Wr(0x34);        // DL: 8 bits, M: two line, SL: 1:18, H: normal instruction set

        I2C1_Wr(0x80);        // DDRAM Address set to 00hex

        I2C1_Wr(0x02);        // return home

        I2C1_Stop();          // Fin de l'I2C
    }
/*##################################################################################
##############################    EFFACE L’ÉCRAN    ################################
##################################################################################*/
void efface_ecran()
  {
      char i = 0 ;          // Variable temporaire dans la fonction

      I2C1_Start();         // Ouverture d'une Com I2C
      I2C1_Wr(LCD_ADR);     // Envoi de l'adresse esclave
      I2C1_Wr(0x00);        // Byte de contrôle pour envoyer une instruction
      I2C1_Wr(0x80);        // INSTRUC : positionne le curseur à l'ADDR : 1ere ligne de 80 à 8F
      I2C1_Repeated_Start();// Répétition de l'ouverture de la com I2C
      I2C1_Wr(LCD_ADR);     // Envoi de l'adresse esclave
      I2C1_Wr(0x40);        // Byte de contrôle pour envoyer une DATA
        for ( i=0;i<=15;i++)// Boucle pour répéter 16 fois l'action sur la première ligne
       {
        I2C1_Wr(0xA0);      // Envoie d'un caractère "vide"
       }

      I2C1_Repeated_Start();// Répétition de l'ouverture de la com I2C
      I2C1_Wr(LCD_ADR);     // Envoi de l'adresse esclave
      I2C1_Wr(0x00);        // Byte de contrôle pour envoyer une instruction
      I2C1_Wr(0xC0);        // INSTRUC : position de l'ADDR du curseur 2ieme ligne de C0 à CF
      I2C1_Repeated_Start();// Répétition de l'ouverture de la com I2C
      I2C1_Wr(LCD_ADR);     // Envoi de l'adresse esclave
      I2C1_Wr(0x40);        // Byte de contrôle pour envoyer une DATA
        for ( i=0;i<=15;i++)// Boucle pour répéter 16 fois l'action sur la deuxième ligne
       {
        I2C1_Wr(0xA0);      // Envoie d'un caractère "vide"
       }

    I2C1_Stop();            // Fin de l'I2C
   }


Astuces perso :
- Étant novice j'aime bien faire clignoter une LED pour voir l'état de mon programme .

Le résultat en vidéo:
http://www.dailymotion.com/video/x36m35h
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Ecran LCD en I²C avec PCF2119
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 1028
Âge : 67
Enregistré en : juillet 2015
Localisation : 01120
Contact :

#2 Message par paulfjujo » mer. 23 sept. 2015 15:52

Bonjour,

Ce post pour denoncer
un piege qui n'est surtout pas démontré par les exemples fournis par MikroE ..
les problemes apparaissant à partir d'une certaine taille de code (et don d'usage RAM).

Code : Tout sélectionner

char *text;                      // Création d'un pointeur nommé text     


Attention, il y a un risque potentiel d'ecrasement memoire avec l'usage d'un pointeur
non initialisé sur une table (un espace memoire defini)
dans ton code , le risque est actuellemnt null, car usage de chaine de caracteres dans le code..
mais avec l'usage de partie variable il serait judicieux d'initialiser
le pointeur txt sur une zone de TEXTE tel que:

Code : Tout sélectionner


char TEXTE
[17];   // string jusqu'à 16 car + zero terminateur
char *txt;  


initialiser le pointeur dans le main

Code : Tout sélectionner

txt=&TEXTE[0]; 


MikroC consomme de la RAM, meme si on met le texte en direct dans le programme.
ce qui occasione de nombreux deboires avec les PIC ayant peu de RAM.
Ce n'est pas le cas avec ce PIC, mais une bonne approche, passe partout,
est de copier le Texte ecrit "en dur" dans le programme , ou texte defini en Flash ROM
dans une zone RAM bien definie (table TEXTE[]) en utilisant :

Code : Tout sélectionner

// --- Copie le texte depuis ROM vers RAM
void strConstRamCpy(char *dest, const char *source
{
  while(*
source) *dest++ = *source++ ;
  *
dest ;    // terminateur
}

exemple d'usage
     strConstRamCpy(txt,"Mesure ANA  ADC0");
     LCD_Write_Text(1,txt);


La taille RAM occupée pour afficher n'importe quel texte en dur de 16 car
ne depassera jamais la partie reservee par la table TEXTE[17]
alors que si on utilise 20 fois un affichage avec le texte en dur dans l'instruction
on utilise 20x16 bytes en RAM.

ce qui à terme peut engendrer des effets indesirable.
Le compilateur compilant le tout avec Zero erreur et message compilation reussie ..
mais avec un warning 102, si les warnings sont activsés !, qui fait toute la difference..
voir les nombreux posts à ce sujet sur Mikro C pro Fourum.

Une alternative est de definir une fonction specifique pour TEXTE residant dans le code
simplement en modifiant le type passé pour la variable pointeur de texte
rajout de const => stockage en FLASH au lieu de RAM

Code : Tout sélectionner

void  affiche_CText(char lignechar colonne,const  char *text)  
{
.. 
etc 
} ; 


nota: c'est ce que je fait avec ma fonction

Code : Tout sélectionner

   UART1_Write_CText(" Init Display LCD2119\r\n"); 

prevue pour l'UART (RS232)
au lieu de la fonction original MikroC UART1_Write_Text(txt);


d'autres solutions existent:
utiliser l'EEPROM du PIC ,
utiliser la zone FLASH ROM
pour stocker les textes à afficher


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité