PIC16F690 et afficheur LCD 1x16
Répondre à la discussion
Affichage des résultats 1 à 21 sur 21

PIC16F690 et afficheur LCD 1x16



  1. #1
    bugdamon

    PIC16F690 et afficheur LCD 1x16


    ------

    Bonjour à tous,

    Je me suis cassé la tête toute la journée et je n'arrive à rien, c'est pourquoi je fais appel à votre aide.

    J'essaye de piloter un afficheur LCD 1x16 ref GDM1601C -> datasheet

    J'ai essayé plusieurs fichiers qui fonctionnent sous CC5x et il m'est impossible d'afficher quoi que ce soit.

    J'ai branché les connecteurs Data 4,5,6 et 7 aux bornes RC0,RC1,RC2 et RC3.

    RS et EN respectivement sur RC4 et RC5, RW est à la masse.

    Merci à tous de votre aide !

    Voici mon code commenté :

    #define ICD_DEBUG
    #pragma config = 0x3F39
    /**************************Defi ne**************************** *******/
    #define TRUE 1
    #define FALSE 0
    /*************************defin e LCD*************************** ***/
    #define RS PORTC.4 // Port RC4
    #define EN PORTC.5 // Port RC5
    #define flag_busy PORTC.3 // Port RC3

    const char buffer[] = "Test LCD ";

    /*********************** Function LCD *****************************/
    void init_lcd(void);
    void lcd_puts(const char *);
    void lcd_putch(unsigned char);
    void lcd_write_instr(unsigned char );
    void lcd_write(unsigned char );
    void lcd_busy(void);
    void LCD_STROBE(void);
    void lcd_home(void);
    void lcd_clear(void);
    void lcd_pos(unsigned char, unsigned char);
    void delayms( char millisec);

    /************* Debut du main *************************/
    void main()
    {
    //configuration PortC en sortie
    TRISC = 0x00;

    OPTION = 0xCF;
    GIE=0; //disable all interrupt

    //configuration pour le LCD
    init_lcd();
    lcd_home();
    lcd_clear();
    //Le programme tourne dans cette boucle principale
    while(1)
    {
    delayms(500);
    lcd_pos(0,0);
    lcd_puts(buffer);
    lcd_pos(1,0);
    lcd_putch('t');
    }

    }
    /********** Fin du main ****************************** */

    /****************************** ****************************** ********/
    void LCD_STROBE(void)
    {
    EN = 1;
    #asm
    nop
    nop
    #endasm
    EN = 0;
    }

    /****************************** ****************************** ********/
    // Test le bit BF jusqu'a ce que le LCD soit ok
    void lcd_busy(void)
    {
    static bit BF;
    /*met en entree RC3*/
    TRISC.3=1;
    RS = 0; // selectionne registre

    do
    {
    EN=1;
    BF=flag_busy;
    EN=0;
    LCD_STROBE(); // lecture deuxieme demi-octet
    }while(BF); // tant que BF=1

    /*met en sortie RC3*/

    TRISC.3=0;
    }
    /****************************** ****************************** ********/
    // Ecriture d'un octet dans le LCD en mode 4 bits
    //Most significant bit first
    void lcd_write(unsigned char c)
    {
    char temp;

    temp= (c>>4);
    PORTC = temp;
    LCD_STROBE();

    PORTC = c;
    LCD_STROBE();
    }
    /****************************** ****************************** ********/
    //Ecrit une instruction dans LCD
    void lcd_write_instr(unsigned char c)
    {
    lcd_busy();
    RS = 0; // selectionne registre
    lcd_write(c);
    }
    /****************************** ****************************** ********/
    // Ecriture d'un caractere
    void lcd_putch(unsigned char c)
    {
    lcd_busy();
    RS = 1;
    lcd_write(c);
    }
    /****************************** ****************************** ********/
    // Ecriture d'une chaine de caracteres
    void lcd_puts(const char * s )
    {
    while(*s )
    lcd_putch(*s++);

    }
    /****************************** ****************************** ********/
    /* initialise l'afficheur LCD en mode 4 bits */
    void init_lcd(void)
    {
    char cpt;

    RS = 0; // registre de controle
    EN = 0;
    delayms(15); // Attente power on
    PORTC = 0x03; //ecrit 03 sur RC4:RC7 et recopie le reste
    LCD_STROBE();
    delayms(4);

    PORTC = 0x03; //ecrit 03 sur RC4:RC7 et recopie le reste
    LCD_STROBE();

    /*delay=10+x*10 100us wait */
    for (cpt=0;cpt<9;cpt++)
    {
    #asm
    nop //1 cycle=1 usec
    #endasm
    }
    PORTC = 0x03; //ecrit 03 sur RC4:RC7 et recopie le reste
    LCD_STROBE();
    /*delay=10+x*10 100us wait */
    for (cpt=0;cpt<9;cpt++)
    {
    #asm
    nop //1 cycle=1 usec
    #endasm
    }

    PORTC = 0x02;
    LCD_STROBE();
    lcd_busy();

    lcd_write_instr(0x28); // Mode 4 bit, 1/16, font 5x8 Function set
    lcd_write_instr(0x0D); // display off
    lcd_write_instr(0x01); // display on, blink cursor on
    lcd_write_instr(0x06); // entry mode

    }
    /****************************** ****************************** ********/
    void lcd_pos(unsigned char ligne,unsigned char pos)
    /*positionne le cursor ligne, position*/
    /*la premiere ligne est 0*/
    {
    char temp,temp1;
    temp=(ligne*0x40);
    temp1=temp+pos;
    lcd_write_instr(temp1+0x80);
    }
    /****************************** ****************************** ********/
    void lcd_clear(void)
    /*efface screen*/
    {
    lcd_write_instr(0x01);
    }
    /****************************** ****************************** ********/
    void lcd_home(void)
    /*curseur home*/
    {
    lcd_write_instr(0x02);
    }
    /****************************** ****************************** ********/
    void delayms( char millisec)
    // Delays a multiple of 1 milliseconds at 4 MHz
    // using the TMR0 timer
    {
    OPTION = 2; /* prescaler divide by 8 */
    do {
    TMR0 = 0;
    clrwdt(); // only if watchdog enabled
    while ( TMR0 < 125) // 125 * 8 = 1000
    ;
    } while ( -- millisec > 0);
    }

    -----

  2. #2
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonsoir bugdamon,
    Voici quelques pistes ...
    En survolant ton code, je vois : RW est à la masse.
    Comment fonctionne alors la fonction : void lcd_busy(void); ?
    La fonction : void init_lcd(void); comporte deux fois " PORTC = 0x03; "
    De mémoire, il me semble qu'il faut envoyer ce code trois fois ...
    Les afficheurs 1 X 16 sont en général des 2 X 8 ! Et celui-çi ?

    Bonne soirée, mictour.

  3. #3
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    Bonsoir et merci de ta réponse,
    Pourquoi dois-je faire 3x PORTC=0x03 ?
    Il me semble que l'afficheur est un 2x8 mais je devrais quand même avoir quelque chose d'affiché sur la moitié de l'écran non ?
    Sinon je peux brancher RW sur RC3 à ce que tu me dis ?

    Merci de votre aide à tous !

  4. #4
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    D'ailleurs il le fait trois fois dans init_lcd non ?

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

    Re : PIC16F690 et afficheur LCD 1x16

    J'ai trouvé ça si ça peut vous aider, désolé je suis un newbie

    "Found DDRAM addresses 0x00..0x07 + 0x40..0x47 to be functional for a 1*16 display size.
    Make/model: Xiamen Ocular / GDM1601c"

  7. #6
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour bugdamon,


    /* Après un simulation de ton code, l'affichage donne ... n'importe quoi !
    Etant bien conscient qu'une simuation n'est qu'une simuilation, surtout quand le temps intervient !
    Toutefois ta routine d'écriture me surprends ...

    Voici les routines de base dont je "" m'inspire "" !

    Auteur :
    ubasics.com/adam/electronics/lcd/cc5xlcd.c

    ( ATTENTION : PORTA )
    */
    void write4(uns8 nyble)
    {
    uns8 temp;
    nyble &amp;= 0xf; // Prepare to send the nibble (4 bits) by getting rid of the top four
    temp = PORTA &amp; 0xf0; // Store the current state of bits 7-4 of PORTA in temp
    temp |= nyble; // OR the PORTA state and nibble to be sent together
    PORTA = temp; // Write 7-4 of PORTA and 3-0 of nyble to PORTA

    EN=1; // Bring enable high
    nop(); // Wait a teensy bit
    EN=0; // Bring Enable Low

    return; // Return nothing
    }

    void write8(uns8 byte)
    {
    uns8 nibble;
    nibble = (byte &amp; 0xf0) &gt;&gt; 4; // Rotate the high 4 bits (7-4) of byte into bits (3-0) of nibble
    write4(nibble); // Write the high 4 bits to the LCD
    nibble = byte &amp; 0xf; // Copy the low four bits of byte into the low four bits of nibble
    write4(nibble); // Write the low 4 bits to the LCD
    }

    void initlcd(void)
    {
    delayms(20); // Wait for LCD to power up ( &gt;15ms )
    RS=0; // Set RS low for instruction
    write4(3); // Set interface to 8 bits
    delayms(5); // Wait for LCD execute instruction ( &gt;4.1ms )
    write4(3); // Set interface to 8 bits
    delayms(1); // Wait for LCD execute instruction ( &gt;100us )
    write4(3); // Set interface to 8 bits
    delayms(5); // Wait for LCD execute instruction (At this point
    // we could actually start using the busy flag)
    write4(2); // Set the display to 4 bit interface
    delayms(5); // Wait for LCD execute instruction
    write8(0x28); // Set the display to two line and ???
    delayms(5); // Wait for LCD execute instruction
    write8(6); // ???
    delayms(5); // Wait for LCD execute instruction
    write8(1); // Clear the LCD
    delayms(5); // Wait for LCD execute instruction
    write8(0xf); // ???
    delayms(5); // Wait for LCD execute instruction
    return;
    }

    void main(void)
    {
    uns8 x; // x is a temporary variable, unsigned byte (0-255)

    PORTA = 0b.0000.0000; // All ports low at start
    PORTB = 0b.0000.0000;
    PORTC = 0b.0000.0000;

    TRISA = 0b.1100.0000; // 7:6 Input(1), 5:0 Output(0)
    TRISB = 0b.1111.1111; // 7:0 Input
    TRISC = 0b.1111.1111; // 7:0 Input

    initlcd(); // Initialize LCD

    while(1)
    {
    // This loop will 'blink' the init message by writing
    // it to the LCD and clearing it twice a second

    delayms(250); // Delay for 1/4 of a second
    RS=1; // Select the data register
    for(x=0;x &lt; 16;x++) // Initmsg has 16 characters, send each one in turn
    write8(initmsg(x)); // Write the initmsg on the screen
    delayms(250); // Delay for 1/4 of a second
    RS=0; // Select the Instruction Register
    write8(0x01); // Clear LCD and move to position one, line one
    }
    }

    Bonne journée, mictour.

  8. #7
    invite03481543

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour mictour,

    autant l'écriture du code de bugdamon en C m'inspire on voit clairement les registres et les fonctions d'appel au LCD, autant ton code à un coté vomitif.

    Je ne vois vraiment pas comment ce code peut t'inspirer, c'est un vrai charabia de la paté de C, décidément CC5x n'est pas mon ami.

  9. #8
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour et merci de vos réponses !

    Si je comprends bien ton code Mictour, les bits de données du LCD doivent être reliés aux port A bit RA0, RA1, RA2 et RA3 ?!
    Sinon ton code n'utilise pas du tout RW, donc je le laisse à la masse comme sur mon montage ?

    Sinon pour les adresses du LCD que j'ai donné avant, quel partie du code dois-je modifier pour que les données aillent bien dans la DDram du lcd aux bonnes adresses ?

    Merci.

  10. #9
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour HULK28,

    Je respecte tes choix et tes préférences jusque dans leurs ... immodérations !
    L'auteur de ce compilateur nous dit lui-même :

    CC5X is not a full C compiler. There are restrictions to be aware
    of.

    Dans le but affirmé de coller au plus près de la "bête".

    Conçu comme un super assembleur, c'est dans cet esprit que je l'utilise et il me permet de gagner beaucoup de temps !
    Oublié les banques et les tests si faciles à mélanger, et en asm je ne m'en privais pas !
    Les fichiers .asm et .lst sont faciles à lire et au besoin à modifier.
    CC5X me convient bien, c'est mon choix, et je l'assume. Quant la norme AINSI, Heu ... ainsi soit-il ! (booof)

    Puis-je avoir une petite pensée pour ADAM ?

    Bon dimanche, mictour.

  11. #10
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    Mictour, peux-tu répondre à mes questions s'il te plait ?
    Je suis un peu perdu, désolé de te prendre la tête

  12. #11
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    CC5 ne reconnait pas uns8 :

    void write4(uns8 nyble)
    ^------
    Error[1] C:\Documents and Settings\Administrateur\Mes documents\Electronique\Test_un ieme\main.c 4 : Syntax error
    (The expression must be corrected. The marker ^------ shows
    the approximate position where CC5X gives up. The documentation
    should be checked if the cause is not obvious)



    Je ne comprends plus rien !
    Need help please !

  13. #12
    invite03481543

    Re : PIC16F690 et afficheur LCD 1x16

    Désolé mictour ce n'était qu'une réaction épidermique, je respecte aussi ton choix, sans rancunes j'espère.

  14. #13
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    Voici le code que je continue à essayer : http://pastebin.com/m43531cd0

    Toujours rien à l'écran pourtant les ports C sont ok (j'ai branché des LEDS pour tester), ça compile, ça se lance sur le 16f690. Je suis complètement perdu, pouvez-vous m'aider ?

    Les broches D4, D5, D6 et D7 sont sur les ports C0 C1 C2 et C3 du microcontroleur, RS sur C4 et EN sur C5.

    Merci de cotre aide.

  15. #14
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour HULK28,

    Aucun problème, je vois et respecte ton travail ici depuis que je fréquente ce forum.
    A bientôt j'espère, mictour.

  16. #15
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour bugdamon



    Comme je te l'explique plus haut, j'ai testé ton code sur simulateur donc je l'ai compilé sans problème. Comme je n'utilise pas MPLAB mais CC5X seul j'ai ajouter " #pragma chip PIC16F877A " en tête du programme.

    "uns8" passe. Fanchement, je ne comprends pas ce qui t'arrive à ce niveau.
    Peut-être un problème de copier - coller à repétition ? J'ai déja rencontré ce cas et l'ai résolu simplement en Re-tapant le passage rejeter ! !

    Tiens moi au courant, mictour.

  17. #16
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    Bon, j'avance peu à peu, j'ai un affichage à l'écran mais pas de ce que je veux et en plus c'est des caractères bizarres que sur une moitié de l'écran.
    Ceci dit certaines cases s'assombrissent quand le programme se déroule, il y a quand même un mouvement.
    Comme je te dis, le programme compile impecable, j'utilise ce code :
    http://pastebin.com/m43531cd0

    Si tu vois une manière de l'adapter a mon 1x16 (2x8 en fait si j'ai compris), je t'en serais reconnaissant.

    Merci de ton aide.

  18. #17
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Regarde ici,

    http://home.iae.nl/users/pouweha/lcd/lcd0.shtml

    Un très bon site. tu y trouveras toutes les données dont tu as besoin pour commencer, plus des exemples bien utiles quand on débute.
    Si ça ne passe toujours pas, envoie - moi ton dernier code, que je le teste. ( J'utilise PICSIMULATOR IDE )

    Oui : 2x8, d'ou l'écriture sur une seule moitié.
    Pour les caractères bizarres, vérifie les "nibbles" le problème vient très problablement de là. Au cours de mon petit essai, j'ai eu droit au même
    blagues!
    mictour.

  19. #18
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    Salut Mictour et merci beaucoup de ton aide, le programme compile bien, et j'ai un affichage.
    Bon j'ai des caracteres bizarres qui restent les mêmes quoi que j'essaye d'afficher.

    J'ai quelques questions encore, comment puis-je afficher correctement la phrase, et surtout, comment modifier le programme pour lui dire de sauter à l'@ 0x40 quand il arrive au milieu de l'écran pour afficher sur la totalité de l'écran ?

    Voici mon code :
    http://pastebin.com/m71fe910b

    Merci beaucoup.

  20. #19
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonsoir bugdamon,

    Comme tu fais des efforts, je te propose un petit bout de code exemple à adapter à ton programme.

    // #include "INT16CXX.H" Tu as vraiment besoin des interruptions ?
    #pragma chip PIC16F877A // nécessaire pour moi !
    #pragma config |= 0x3f32 // Pour éviter quelques quelques ennuis éventuels.
    // ... je n'ai pas analysé ton mot de config.

    void main( void)
    {
    char i;
    initlcd();
    // Autres init, config ... GIE = 0; ...

    RS = 1; // LCD en mode écriture
    // envoie les 8 caractères de initmsg1() (de 0 à 7 )
    for(i=0; i<8; i++)
    write8(initmsg1(i));

    // On se positionne en "deuxième ligne"
    RS = 0; // LCD en mode commande
    write8(0b11000000 ); // Début de la 2.ie ligne (de 8 à 15)

    RS = 1; // on repasse en mode écriture.
    // Puis on envoie la deuxième phrase
    for(i=0; i<8; i++) write8(initmsg2(i));
    // etc...
    while(1); /* Je le place ici pour ne pas faire tourner le programme en boucle et donc "figer" l'affichage.
    Mais je n'ai pas fait de simulation. J"espère que : write8(0b11000000 ); est correct. */
    }

    Bonne soirée, mictour.

  21. #20
    bugdamon

    Re : PIC16F690 et afficheur LCD 1x16

    J'ai une bonne nouvelle !
    Ca marche du tonnerre !

    J'ai essayé sur un PIC16F505 et ça marchait bien, j'avais du mal à faire fonctionner correctement le programme sur le 16F690 et en cherchant un peu, c'était un problème de comparateurs et de pins analogues. Je les désactive donc à l'initialisation.

    Merci beaucoup de ton aide Mictour, je poste mon code, ça pourra peut être en aider d'autres et comme ça tu pourras voir ma fonction qui permet de gérer les 2 afficheurs x 8 caractères.

    LCD by Bug

    Pour finir, j'ai encore une question, je voudrais visualiser des variables sur l'écran (des int je pense), est-il possible de transformer un int en *char afin de pouvoir utiliser ma fonction d'affichage pour visualiser la sortie de l'ADC par exemple ?

    Merci encore !

  22. #21
    mictour

    Re : PIC16F690 et afficheur LCD 1x16

    Bonjour bagdamon,

    Bravo, tes efforts n'ont pas été vains !
    Voici le code que tu me demandes, plus quelques autres.
    Ces routines de conversion sont optimisées, donc ne les modifier qu'en connaissance de cause...
    Ce serait sympa que tu les ajoutes à ton code exemple ...

    // AUTEUR : William Sandqvist (SUEDE)

    /* ascnum.c Functions to converts between variables and ASCII-string */
    /* Include processor header file in main program */
    /* Include "math16.h" in main program */
    /* Declare global string s[11] in main program */

    /* Function prototypes is in ascnum.h */


    /* FROM BINARY NUMBERS TO ASCII-STRINGS */

    /* chartoa: convert "char" unsigned 8 bit variable c
    to ASCII-characters in global string s[] */

    // #include "math16.h" Pour compiler CE fichier
    // char s[11];
    void chartoa(char c)
    {
    char i,temp;
    s[3]='\0';
    for (i = 2; ;i--)
    {
    temp = c % 10;
    temp += '0';
    s[i]=temp;
    if (i==0) break;
    c /= 10;
    }
    }


    /* inttoa: convert int variable i8 with sign
    to ASCII-characters in global string s[] */
    void inttoa(int i8)
    {
    char i,temp;
    s[4] = '\0';
    s[0] = '+'; if (i8.7 == 1) {i8 = - i8; s[0] = '-';}
    for (i = 3; ;i--)
    {
    temp = i8 % 10;
    temp += '0';
    s[i]=temp;
    if (i==1) break;
    i8 /= 10;
    }
    }


    /* unslongtoa: convert unsigned long variable u16
    to ASCII-characters in global string s[] */
    void unslongtoa(unsigned long u16)
    {
    char i,temp;
    s[5] = '\0';
    for (i = 4; ;i--)
    {
    temp = u16 % 10;
    temp += '0';
    s[i]=temp;
    if (i==0) break;
    u16 /= 10;
    }
    }


    /* longtoa: convert long int variable i16
    to ASCII-characters in global string s[] */
    void longtoa(long i16)
    {
    char i,temp;
    s[6] = '\0';
    s[0] = '+'; if (i16.15 == 1) {i16 = - i16; s[0] = '-';}
    for (i = 5; ;i--)
    {
    temp = i16 % 10;
    temp += '0';
    s[i]=temp;
    if (i==1) break;
    i16 /= 10;
    }
    }


    /* FROM ASCII-STRING TO BINARY NUMBER */

    char atochar( void ) /* converts ASCII-inputstring in s[] to char */
    /* Inputstring must have three digits 000 ... 255 */
    {
    char number, digit;
    digit = s[2]; /* ones digit */
    digit = digit - '0';
    number = digit;

    digit = s[1]; /* tenths digit */
    digit = digit - '0';
    digit = digit*10;
    number = number + digit;

    if( s[0]=='1')
    {
    /* hundreds digit */
    number = number + 100;
    }
    if( s[0]=='2' )
    {
    /* hundreds digit */
    number = number + 200;
    }

    return number;
    }

    Bonne continuation, mictour.

Discussions similaires

  1. afficheur lcd en afficheur 7 segment
    Par invite3cc40cdb dans le forum Électronique
    Réponses: 3
    Dernier message: 04/02/2008, 09h43
  2. LCD 1x16
    Par invite60243f9b dans le forum Électronique
    Réponses: 9
    Dernier message: 18/11/2007, 19h45
  3. Afficheur LCD
    Par invite854748b1 dans le forum Électronique
    Réponses: 3
    Dernier message: 18/06/2007, 19h25
  4. Afficheur Lcd
    Par invite436dc8ee dans le forum Électronique
    Réponses: 5
    Dernier message: 22/05/2006, 09h54
  5. Afficheur lcd
    Par invite3837a451 dans le forum Électronique
    Réponses: 4
    Dernier message: 17/11/2003, 20h12
Découvrez nos comparatifs produits sur l'informatique et les technologies.