Programmation LCD 2x16 PIC182550
Répondre à la discussion
Affichage des résultats 1 à 8 sur 8

Programmation LCD 2x16 PIC182550



  1. #1
    invite33954b8a

    Programmation LCD 2x16 PIC182550


    ------

    Bonjour,

    Je suis actuellement en train de travailler sur un décodeur DTMF et mon problème est le suivant :

    Je veux tout d'abord afficher, avec mon LCD, une lettre sur mon afficheur.

    J'ai avant tout déjà testé mon PIC pour voir si les connections se faisaient avec un petit programme pour allumer la diode et ceci marché sans problème. Mes connections se font bien sur l'afficheur donc ça ne peut provenir que du programme qui est le suivant :

    LCD.c

    #include <p18f2550.h>
    #include "LCD4bits.h"
    #include <delays.h>

    #pragma config WDT = OFF

    void main (void)
    {
    /* PORTB RB0,RB1,RB2,RB3 sortie, pour l'afficheur */
    TRISBbits.TRISB0 = 0;
    TRISBbits.TRISB1 = 0;
    TRISBbits.TRISB2 = 0;
    TRISBbits.TRISB3 = 0;

    Delay100TCYx (2);

    TRISCbits.TRISC0 = 0;
    TRISCbits.TRISC1 = 0;
    TRISCbits.TRISC2 = 0;

    init_lcd (0);
    aff_car ('A');
    }

    LCD.h

    /*============================= ============================== ========================*/
    #include <delays.h>

    #ifndef LCD4BITS_H //facultatif (mais il faut faire attention de ne pas inclure
    #define LCD4BITS_H //le même .h plus d'une fois dans un projet).

    typedef unsigned char byte; //facultatif pour Code Warrior.
    typedef unsigned int word; //Idem.
    typedef unsigned long dword; //Idem.

    /****************************** ****************************** *************************/
    /* Déclaration d'un champ de bits */

    union {

    struct { //une structure 8 bits (champ de bits).
    byte bit0:1,
    bit1:1,
    bit2:1,
    bit3:1,
    bit4:1,
    bit5:1,
    bit6:1,
    bit7:1;
    }bits;
    byte octet; //un byte (octet).
    } mon_octet ; //accès à l'octet complet par mon_octet.octet et
    //accès aux bits par mon_octet.bits.bitx .

    /****************************** ****************************** *************************/
    /* Définition des broches utilisées */

    //bits de données du LCD = utilisation des 4 broches du micro au choix:
    #define DATA4 PORTBbits.RB0 //bit 3 du PORTB ou toute autre broche.
    #define DATA5 PORTBbits.RB1 //bit 4 du PORTB ou toute autre broche.
    #define DATA6 PORTBbits.RB2 //bit 5 du PORTB ou toute autre broche.
    #define DATA7 PORTBbits.RB3 //bit 6 du PORTB ou toute autre broche.

    //bits de direction des broches de données:
    #define DDR_DATA4 TRISBbits.TRISB0 // bit de direction de la broche PTB_PTB3.
    #define DDR_DATA5 TRISBbits.TRISB1
    #define DDR_DATA6 TRISBbits.TRISB2
    #define DDR_DATA7 TRISBbits.TRISB3

    //bits de commande du LCD = utilisation des 3 broches du micro au choix:
    #define LCD_RS PORTCbits.RC1 //LCD_RS = bit 0 du PORTB ou toute autre broche.
    #define LCD_RW PORTCbits.RC2 //LCD_RW = bit 1 du PORTB ou toute autre broche.
    #define LCD_E PORTCbits.RC0 //LCD_E = bit 2 du PORTB ou toute autre broche.

    //bits de direction des broches de commande:
    #define DDR_LCD_RS TRISCbits.TRISC1 // bit de direction de la broche PTB_PTB0.
    #define DDR_LCD_RW TRISCbits.TRISC2
    #define DDR_LCD_E TRISCbits.TRISC0

    /* Déclaration des fonctions élaborées */

    void ecr_ctrl(byte ctrl);
    void ecr_data(byte data);
    void busy_lcd(void);
    void init_lcd(byte curseur);
    void xy_lcd(byte x, byte y);
    void aff_car(byte c);
    void aff_txt(byte *message);
    void efface_lcd(void);
    void defini_cars(const byte *c, byte char_code);
    void onoff_lcd(byte onoff);

    void aff_base(dword hexa, byte base);
    void aff_float(float data, byte decimale);
    void aff_CAN(byte CAN, byte decimal);
    void aff_heure(byte heures, byte minutes, byte secondes);

    /* Temporisation logicielle: */

    void tempo_ms(word temps);

    //****************************** ****************************** *************************

    const byte *h="0123456789ABCDEF";

    //****************************** ****************************** *************************
    //#include "car_spec.h" //table définissant quelques caractères spéciaux.

    /****************************** ****************************** **************************
    void ecr_ctrl(byte ctrl)

    ****************************** ****************************** **************************/
    void ecr_ctrl(byte ctrl){

    //utilise la variable mon_octet.octet pour avoir accès aux bits de ctrl :
    mon_octet.octet=ctrl;

    //met d'abord les 4 bits de poids forts de ctrl sur les 4 lignes DATA 7-4 utilisées du LCD
    //(mode 4 bits)

    PORTB = ( ( ctrl >> 4 ) & 0x0F );

    LCD_RS=0; //envoie un octet de commande.
    LCD_RW=0; //écriture dans la RAM du LCD.
    LCD_E=1; //validation par l'impulsion E.
    LCD_E=0;

    //met par la suite les 4 bits de poids faible de ctrl sur les 4 lignes DATA 7-4
    //utilisées du LCD (mode 4 bits)

    PORTB = ( ctrl & 0x0F );

    LCD_E=1; //validation par l'impulsion E.
    LCD_E=0;

    //test du bit Busy ou attente de #2ms pour que le LCD soit prêt.
    busy_lcd();
    }

    /****************************** ****************************** **************************
    void ecr_data(byte data)

    Envoie un octet de donnée data dans la RAM du LCD.
    ****************************** ****************************** **************************/
    void ecr_data(byte data){

    //utilise la variable mon_octet.octet pour avoir accès aux bits de data.
    mon_octet.octet=data;

    //met d'abord les 4 bits de poids forts de data sur les 4 lignes DATA 7-4 utilisées du
    //LCD (mode 4 bits)

    PORTB = ( ( data >> 4 ) & 0x0F );

    LCD_RS=1; //envoie un octet de donnée.
    LCD_RW=0; //écriture dans la RAM du LCD.
    LCD_E=1; //validation par l'impulsion E.
    LCD_E=0;

    //met par la suite les 4 bits de poids faible de ctrl sur les 4 lignes DATA 7-4
    //utilisées du LCD (mode 4 bits)

    PORTB = ( data & 0x0F );

    LCD_E=1; //validation par l'impulsion E.
    LCD_E=0;

    //test du bit Busy ou attente de #2ms pour que le LCD soit prêt.
    busy_lcd();
    }

    /****************************** ****************************** **************************
    busy_lcd(void)

    ****************************** ****************************** **************************/
    void busy_lcd(void){

    int i;

    for (i = 0; i < 5000; i++)
    ;

    }

    /****************************** ****************************** **************************
    void init_lcd(byte curseur)

    Initialise le LCD et les PORTs utilisés.

    void init_lcd(byte curseur){

    //initialise les 4 lignes DATA 7-4 du micro utilisé en sortie.
    // DDR_DATA4=1;
    // DDR_DATA5=1;
    // DDR_DATA6=1;
    // DDR_DATA7=1;

    //initialise les broches de contrôle du LCD en sortie.
    // DDR_LCD_RS=1;
    // DDR_LCD_E=1;
    // DDR_LCD_RW=1;

    busy_lcd(); //test du bit Busy ou attente de #50ms pour que le LCD soit prêt.



    ecr_ctrl(0x28); //adressage 4 Bits, afficheur 2 lignes.
    ecr_ctrl(0x06); //incrémente l'adresse DD-RAM (l'affichage se décale vers la
    //droite).
    ecr_ctrl(0x01); //effacement de l'écran et curseur positionné en haut à gauche.

    switch(curseur){

    case 0:
    ecr_ctrl(0x0C); //curseur hors service, affichage actif.
    break;

    case 1:
    ecr_ctrl(0x0E); //curseur en service, affichage actif.
    break;

    case 2:
    ecr_ctrl(0x0F); //curseur clignotant en service.
    break;

    default:
    break;
    };
    }

    /****************************** ****************************** **************************
    void xy_lcd(byte x, byte y)

    Positionne le curseur aux coordonnées (x, y) : 1 <= x <= 16 et 1 <= y <= 2.

    ****************************** ****************************** **************************/
    void xy_lcd(byte x, byte y){

    if (y==1)
    ecr_ctrl(0x80+x-1); //positionne la ligne 1 aux coordonnées (x, 1).

    if (y==2)
    ecr_ctrl(0xC0+x-1); //positionne la ligne 2 aux coordonnées (x, 2).
    }

    /****************************** ****************************** **************************
    void aff_car(byte c)

    Affiche à la position du curseur le caractère dont le code ascii est c.

    ****************************** ****************************** **************************/
    void aff_car(byte c){

    ecr_data (c);
    }

    /****************************** ****************************** **************************

    void aff_txt(byte *message)

    Affiche, à la position du curseur, le texte " message ".

    ****************************** ****************************** **************************/
    void aff_txt(byte *message){

    while(*message!= '\0'){ //écriture sur le LCD de toute la chaîne.

    if(*message=='\r')
    xy_lcd(1,2);
    else
    aff_car(*message); //écriture sur le LCD d'un caractère du message.

    message++;
    };
    }

    /****************************** ****************************** **************************
    void efface_lcd(void)

    Efface l'écran et positionne le curseur en haut à gauche.

    ****************************** ****************************** **************************/
    void efface_lcd(void){

    ecr_ctrl(0x01);
    }

    /****************************** ****************************** **************************
    void defini_cars(const byte *c, char_code)

    ****************************** ****************************** **************************/
    void defini_cars(const byte *c, byte char_code){

    byte i=0,a;
    a=(char_code<<3)|0x40; //les caractères sont logés dans le CGRAM du LCD à partir
    //de l'adresse 0x40.
    for(i=0; i<8; i++){

    ecr_ctrl(a);
    ecr_data(c[i]);
    a++;
    };
    }

    /****************************** ****************************** **************************
    void onoff_lcd(byte onoff)

    ****************************** ****************************** **************************/
    void onoff_lcd(byte onoff){

    if(onoff==1)
    ecr_ctrl(0x0C);
    else
    ecr_ctrl(0x08);
    }

    /****************************** ****************************** **************************
    void aff_base(dword hexa, byte base)

    Affiche, sur le LCD, hexa en base : 2 (binaire) <= base <= 16 (hexadécimale).

    ****************************** ****************************** **************************/
    void aff_base(dword hexa, byte base){

    byte i=0; //compteur.
    static byte buf[32]; //buffer de stockage; static car il est appelé de la
    //fonction aff_float juste après.

    /* remplit buf[i] par le code ascii du résultat de l'opération (hexa%base)
    (cf constante *h déclarée en entête). */
    do{
    buf[i]=h[hexa%base]; //conversion Hexa/ASCII de la fin vers le début.
    hexa=hexa/base;
    i++;
    }while(hexa);

    /* affiche le contenu du buffer, de la fin vers le début et caractère par
    caractère, directement dans la RAM du LCD. */
    do{
    i--;
    aff_car(buf[i]);
    } while(i>0);
    }

    /****************************** ****************************** **************************
    void aff_float(float data, byte decimal)
    Convertit, arrondit et affiche, à la position du curseur, data (type float 32 bits) au
    format décimal avec 1 à 6 décimales.

    ****************************** ****************************** **************************/
    void aff_float(float data, byte decimal){

    byte i;
    dword dec, dec10=10;

    if(data<0){
    aff_car('-'); //si data est négatif affiche '-'.
    data*=-1; //data est rendu positif.
    }

    for(i=0; i< decimal; i++) //dec10=10^(decimal+1).
    dec10*=10;

    dec=dec10*(data-(dword)data);//partie décimale, à (decimal+1) chiffres, est rangé dans dec,

    if(dec%10>=5) //puis arrondis à la valeur supérieure.
    dec+=10;

    if(dec > dec10-1){ //si Overflow,
    data +=1; //ajoute 1 à la partie entière,
    dec=0; //et la partie décimale est mise à 0.
    }

    aff_base(data, 10); //tronque data et affiche la partie entière.

    if(decimal !=0){
    aff_car('.');
    dec10/=100; //dec10=10^(decimal-1).
    dec=dec/10; //dec est à decimal chiffres.

    while(dec/dec10==0 && decimal>1){
    aff_car('0'); //affiche les éventuels zéros à gauche de la
    //partie décimale.
    dec10/=10;
    decimal--;
    }

    aff_base(dec, 10); //affiche le reste de la partie décimale.
    }
    }


    /****************************** ****************************** **************************
    void aff_CAN(byte CAN, byte decimal)

    Le résultat (CAN) de la conversion A/N, issu du CAN du micro, est converti en tension et
    inscrit dans la RAM d'affichage du LCD.

    ****************************** ****************************** **************************/
    void aff_CAN(byte CAN, byte decimal){

    aff_float(5.0*CAN/255, decimal); //plein d'échelle = 5 volts et résolution = 8 bits.

    aff_txt(" V"); //affiche l'unité de mesure.
    }

    /****************************** ****************************** **************************
    void aff_heure(byte heures, byte minutes, byte secondes)

    Affiche à la position du curseur l'heure, sous la forme HH:MM:SS.

    ****************************** ****************************** **************************/
    void aff_heure(byte heures, byte minutes,byte secondes){

    if(heures < 10)
    aff_car('0'); //affiche 0 pour les dizaines.

    aff_base(heures, 10);
    aff_car(':'); //insertion ':'.

    if(minutes < 10)
    aff_car('0'); //affiche 0 pour les dizaines.

    aff_base(minutes, 10);
    aff_car(':'); //insertion ':'.

    if(secondes < 10)
    aff_car('0'); //affiche 0 pour les dizaines.

    aff_base(secondes, 10);
    }

    /****************************** ****************************** **************************
    void tempo_ms(word temps)

    ****************************** ****************************** **************************/

    void tempo_ms(word temps){

    word j=0,i=0;

    for(j = 0;j < temps ; j++) //répète temps x 1ms.
    for(i = 0; i <90 ; i++); //un pas 1ms pour un quartz de 10MHz.
    }

    //****************************** ****************************** *************************

    #endif

    Serait-il possible d'avoir un avis sur ce code et si possible une aide afin de règler ce problème ?

    Ci-joint mon schéma électrique.

    -----
    Images attachées Images attachées  

  2. #2
    sdec25

    Re : Programmation LCD 2x16 PIC182550

    Salut,
    Il manque un petit détail : quel est le problème ?

    Des questions sur les LCD on en voit pratiquement tous les jours sur le forum. Soit c'est l'initialisation qui est mal faite => lire un tuto
    Soit c'est les tempos qui ne sont pas bonnes => les modifier pour respecter celles préconisées par la datasheet de ton écran.

  3. #3
    invite33954b8a

    Re : Programmation LCD 2x16 PIC182550

    Le problème c'est qu'une fois le programme insérer. Mon afficheur s'allume correctement mais affiche des carrés noir sur la première ligne et rien sur la seconde. Ce qui est surement dû à une erreur dans la programmation...

  4. #4
    invite33954b8a

    Re : Programmation LCD 2x16 PIC182550

    Je me permets de faire un petit UP

  5. A voir en vidéo sur Futura
  6. #5
    sdec25

    Re : Programmation LCD 2x16 PIC182550

    Je vois déjà une source de problème :
    Utilisation de PORT au lieu de LAT pour les sorties.
    Fais une recherche sur le forum, il y a beaucoup de topics qui en parlent mais ce n'est pas sûr d'utiliser PORT en sortie au lieu de LAT.

    Pour le reste, comme je l'ai déjà dit, il faut vérifier la séquence d'initialisation (en bas de cette page, en mode 4 bits) et les timings.
    De plus, vérifie que ton busy_lcd attend assez longtemps.

  7. #6
    invite33954b8a

    Re : Programmation LCD 2x16 PIC182550

    Bonjour à tous,

    J'ai réussi à afficher un caractère sur mon afficheur, maintenant je souhaite afficher une chaine de caractère mais j'ai un petit soucis, voici mon code :

    //write a string of chars to the LCD
    void lcd_puts(const char * s){
    while(*s){
    switch (*s) {
    case '\b': lcd_write(0,0x10); break; //backspace
    case '\f': lcd_write(0,0x1); //clear display
    Delay1KTCYx(10);
    break;
    case '\n': lcd_write(0,0xC0); break; //newline
    default : lcd_write(1,*s); // write characters
    break;
    }
    *s++;
    }
    }
    Voici ce que j'ai dans mon main.c

    void main ()
    {
    char temp1[] = "PHILIPPE";
    char temp2[] = "PIERRE-MARIE";

    System_init();
    lcd_init();
    lcd_goto(1,4); // select first line
    lcd_puts(temp1);
    lcd_goto(2,2); // Select second line
    lcd_puts(temp2);

    while (1);
    {

    }
    }

    Avec ça j'arrive bien à afficher "PIERRE-MARIE" sur la deuxième ligne mais sur la première, je n'ai que "PH". Bref comme vous pouvez le constater, j'ai été obliger de créer un "char" pour pouvoir afficher.

    Mon but ici est de pouvoir directement écrire : lcd_puts"PHILIPPE"

    merci d'avance.

  8. #7
    invite25df009a

    Re : Programmation LCD 2x16 PIC182550

    Salut !!

    J'ai eu le même soucie avec cette librairie LCD. Pour l'instant pour remedire au problème j'ai créé 2 fonction affichage que voici :

    void aff_txt(byte *message)
    {

    while(*message!= '\0') //écriture sur le LCD de toute la chaîne.
    {

    if(*message=='\r')
    xy_lcd(1,2);
    else
    aff_car(*message); //écriture sur le LCD d'un caractère du message.

    *message++;
    };
    }

    void aff_txt_rom(rom char *message)
    {

    while(*message!= '\0') //écriture sur le LCD de toute la chaîne.
    {

    if(*message=='\r')
    xy_lcd(1,2);
    else
    aff_car(*message); //écriture sur le LCD d'un caractère du message.

    *message++;
    };
    }
    Tu dois utiliser la deuxième pour afficher directement la chaine de caractère sur le LCD sans passer par un tableau de char !!

    a+

  9. #8
    invite33954b8a

    Re : Programmation LCD 2x16 PIC182550

    Ah ouais, ca marche bien mieux!

Discussions similaires

  1. Afficheur lcd 2x16 programmation
    Par invite960f35e5 dans le forum Électronique
    Réponses: 32
    Dernier message: 29/08/2008, 23h51
  2. Programmation LCD 2x16 en C
    Par invite3c35244f dans le forum Électronique
    Réponses: 6
    Dernier message: 10/10/2007, 09h09
  3. Routine LCD 2X16
    Par invite55fe29e6 dans le forum Électronique
    Réponses: 28
    Dernier message: 07/06/2007, 21h40
  4. Afficheur LCD 2x16
    Par invite308aa073 dans le forum Électronique
    Réponses: 4
    Dernier message: 01/02/2006, 16h11
  5. LCD 2x16 caractères
    Par invite5d44ee6f dans le forum Électronique
    Réponses: 1
    Dernier message: 22/05/2004, 16h33
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...