Pic 18f2221 et lcd MC42003a6w
Répondre à la discussion
Affichage des résultats 1 à 5 sur 5

Pic 18f2221 et lcd MC42003a6w



  1. #1
    jb458

    Pic 18f2221 et lcd MC42003a6w


    ------

    Bonjour à tous

    Je suis nouveau sur le forum et je n'ai que des notions en programmation.
    L'une de mes passions et l’électronique, que je pratique sur mes temps libre.

    J'utilise MPLAB couplé à CCS .
    J'ai déjà utilisé : les timers , les CAN , Interruptions, ... sur des PIC le tout en langage c.

    J'ai fait l’acquisition du écran lcd MC42003A6W sur le site farnell ( lien avec datasheet : http://fr.farnell.com/midas/mc42004a...b-l/dp/2063162 ).
    Après de longue recherche je me suis tourné vers le driver Flex_LCD420.c disponible sur le site de ccs. ( http://www.ccsinfo.com/forum/viewtopic.php?t=28268 )
    Ce qui ma donner le code suivant:

    driver:

    Code:
    
    
    // Flex_LCD420.c
    
    // These pins are for my Microchip PicDem2-Plus board,
    // which I used to test this driver.
    // An external 20x4 LCD is connected to these pins.
    // Change these pins to match your own board's connections.
    
    #define LCD_DB4   PIN_B0
    #define LCD_DB5   PIN_B1
    #define LCD_DB6   PIN_B2
    #define LCD_DB7   PIN_B4
    
    #define LCD_RS    PIN_A3
    #define LCD_RW    PIN_A2
    #define LCD_E     PIN_A4
    
    /*
    // To prove that the driver can be used with random
    // pins, I also tested it with these pins:
    #define LCD_DB4   PIN_D4
    #define LCD_DB5   PIN_B1
    #define LCD_DB6   PIN_C5
    #define LCD_DB7   PIN_B5
    
    #define LCD_RS    PIN_E2
    #define LCD_RW    PIN_B2
    #define LCD_E     PIN_D6
    */
    
    // If you want only a 6-pin interface to your LCD, then
    // connect the R/W pin on the LCD to ground, and comment
    // out the following line.  Doing so will save one PIC
    // pin, but at the cost of losing the ability to read from
    // the LCD.  It also makes the write time a little longer
    // because a static delay must be used, instead of polling
    // the LCD's busy bit.  Normally a 6-pin interface is only
    // used if you are running out of PIC pins, and you need
    // to use as few as possible for the LCD.
    #define USE_RW_PIN   1     
    
    
    // These are the line addresses for most 4x20 LCDs.
    #define LCD_LINE_1_ADDRESS 0x00
    #define LCD_LINE_2_ADDRESS 0x40
    #define LCD_LINE_3_ADDRESS 0x14
    #define LCD_LINE_4_ADDRESS 0x54
    
    // These are the line addresses for LCD's which use
    // the Hitachi HD66712U controller chip.
    /*
    #define LCD_LINE_1_ADDRESS 0x00
    #define LCD_LINE_2_ADDRESS 0x20
    #define LCD_LINE_3_ADDRESS 0x40
    #define LCD_LINE_4_ADDRESS 0x60
    */
    
    int8 i;
    int8 b1, b2, b3, b4;
    //========================================
    
    #define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)
    
    int8 lcd_line;
    
    int8 const LCD_INIT_STRING[4] =
    {
     0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
     0xc,                     // Display on
     1,                       // Clear display
     6                        // Increment cursor
     };
                                 
    
    //-------------------------------------
    void lcd_send_nibble(int8 nibble)
    {
    // Note:  !! converts an integer expression
    // to a boolean (1 or 0).
     output_bit(LCD_DB4, !!(nibble & 1));
     output_bit(LCD_DB5, !!(nibble & 2)); 
     output_bit(LCD_DB6, !!(nibble & 4));   
     output_bit(LCD_DB7, !!(nibble & 8));   
    
     delay_cycles(1);
     output_high(LCD_E);
     delay_us(2);
     output_low(LCD_E);
    }
    
    //-----------------------------------
    // This sub-routine is only called by lcd_read_byte().
    // It's not a stand-alone routine.  For example, the
    // R/W signal is set high by lcd_read_byte() before
    // this routine is called.     
    
    #ifdef USE_RW_PIN
    int8 lcd_read_nibble(void)
    {
    int8 retval;
    // Create bit variables so that we can easily set
    // individual bits in the retval variable.
    #bit retval_0 = retval.0
    #bit retval_1 = retval.1
    #bit retval_2 = retval.2
    #bit retval_3 = retval.3
    
    retval = 0;
       
    output_high(LCD_E);
    delay_us(1);
    
    retval_0 = input(LCD_DB4);
    retval_1 = input(LCD_DB5);
    retval_2 = input(LCD_DB6);
    retval_3 = input(LCD_DB7);
     
    output_low(LCD_E);
    delay_us(1);
       
    return(retval);   
    }   
    #endif
    
    //---------------------------------------
    // Read a byte from the LCD and return it.
    
    #ifdef USE_RW_PIN
    int8 lcd_read_byte(void)
    {
    int8 low;
    int8 high;
    
    output_high(LCD_RW);
    delay_cycles(1);
    
    high = lcd_read_nibble();
    
    low = lcd_read_nibble();
    
    return( (high<<4) | low);
    }
    #endif
    
    //----------------------------------------
    // Send a byte to the LCD.
    void lcd_send_byte(int8 address, int8 n)
    {
    output_low(LCD_RS);
    
    #ifdef USE_RW_PIN
    while(bit_test(lcd_read_byte(),7)) ;
    #else
    delay_us(60); 
    #endif
    
    if(address)
       output_high(LCD_RS);
    else
       output_low(LCD_RS);
         
     delay_cycles(1);
    
    #ifdef USE_RW_PIN
    output_low(LCD_RW);
    delay_cycles(1);
    #endif
    
    output_low(LCD_E);
    
    lcd_send_nibble(n >> 4);
    lcd_send_nibble(n & 0xf);
    }
    //----------------------------
    
    void lcd_init(void)
    {
    int8 i;
    
    lcd_line = 1;
    
    output_low(LCD_RS);
    
    #ifdef USE_RW_PIN
    output_low(LCD_RW);
    #endif
    
    output_low(LCD_E);
    
    // Some LCDs require 15 ms minimum delay after
    // power-up.  Others require 30 ms.  I'm going
    // to set it to 35 ms, so it should work with
    // all of them.
    delay_ms(35);         
    
    for(i=0 ;i < 3; i++)
       {
        lcd_send_nibble(0x03);
        delay_ms(5);
       }
    
    lcd_send_nibble(0x02);
    
    
    for(i=0; i < sizeof(LCD_INIT_STRING); i++)
       {
        lcd_send_byte(0, LCD_INIT_STRING[i]);
       
        // If the R/W signal is not used, then
        // the busy bit can't be polled.  One of
        // the init commands takes longer than
        // the hard-coded delay of 50 us, so in
        // that case, lets just do a 5 ms delay
        // after all four of them.
        #ifndef USE_RW_PIN
        delay_ms(5);
        #endif
       }
    
    }
    
    //----------------------------
    
    void lcd_gotoxy(int8 x, int8 y)
    {
    int8 address;
    
    
    switch(y)
      {
       case 1:
         address = LCD_LINE_1_ADDRESS;
         break;
    
       case 2:
         address = LCD_LINE_2_ADDRESS;
         break;
    
       case 3:
         address = LCD_LINE_3_ADDRESS;
         break;
    
       case 4:
         address = LCD_LINE_4_ADDRESS;
         break;
    
       default:
         address = LCD_LINE_1_ADDRESS;
         break;
         
      }
    
    address += x-1;
    lcd_send_byte(0, 0x80 | address);
    }
    
    //-----------------------------
    void lcd_putc(char c)
    {
     switch(c)
       {
        case '\f':
          lcd_send_byte(0,1);
          lcd_line = 1;
          delay_ms(2);
          break;
       
        case '\n':
           lcd_gotoxy(1, ++lcd_line);
           break;
       
        case '\b':
           lcd_send_byte(0,0x10);
           break;
       
        default:
           lcd_send_byte(1,c);
           break;
       }
    }
    
    //------------------------------
    #ifdef USE_RW_PIN
    char lcd_getc(int8 x, int8 y)
    {
    char value;
    
    lcd_gotoxy(x,y);
    
    // Wait until busy flag is low.
    while(bit_test(lcd_read_byte(),7)); 
    
    output_high(LCD_RS);
    value = lcd_read_byte();
    output_low(LCD_RS);
    
    return(value);
    }
    #endif

    et pour le programme :

    Code:
    void main()
    {
    
    
    
    
    // The lcd_init() function should always be called once,
    // near the start of your program.
    lcd_init();
    
    // Clear the LCD.
    printf(lcd_putc, "\f");
    delay_ms(500);
    
    
    while(1)
      {
       // Test the clear screen and newline commands.
       // Also test that we can write to all 4 lines.
       printf(lcd_putc, "\fThis is the 1st line");
       printf(lcd_putc, "\nNext is the 2nd line");
       printf(lcd_putc, "\nThis is the 3rd line");
       printf(lcd_putc, "\nFinally the 4th line");
       delay_ms(3000);
    
       // Test some additional characters.
       printf(lcd_putc, "\fABCDEFGHIJKLMNOPQRST");
       printf(lcd_putc, "\nabcdefghijklmnopqrst");
       printf(lcd_putc, "\n12345678901234567890");
       printf(lcd_putc, "\n!@#$^&*(){}[]:;<>?/=");
       delay_ms(3000);
    
       // Clear the LCD.
       printf(lcd_putc, "\f");
       delay_ms(500);
    
       // Test that lcd_gotoxy() works.  Go to each of
       // the four corners and put a number in each one,
       // in a clockwise direction, starting with the upper
       // left corner.
       lcd_gotoxy(4, 2);       
       printf(lcd_putc, "Put a number in");   
       lcd_gotoxy(4, 3);       
       printf(lcd_putc, "each corner.");   
       lcd_gotoxy(1, 1);       
       printf(lcd_putc, "1");   
       lcd_gotoxy(20, 1);       
       printf(lcd_putc, "2");   
       lcd_gotoxy(20, 4);       
       printf(lcd_putc, "3");   
       lcd_gotoxy(1, 4);       
       printf(lcd_putc, "4");   
       delay_ms(3000);
    
    // Read the character that was written in each corner
    // of the LCD and display it.   This tests the lcd_getc()
    // function.   
    // The following test can only be done if we can read
    // from the LCD.  If the RW pin is not used, then the
    // LCD is in write-only mode, and we can't do this test.
    // The #ifdef statement will prevent the code from
    // being compiled, in that case.
    
    #ifdef USE_RW_PIN   
       // Test if lcd_getc() can read
       // a byte from each corner.
       b1 = lcd_getc(1,1);   
       b2 = lcd_getc(20,1);   
       b3 = lcd_getc(20,4);   
       b4 = lcd_getc(1,4);   
       lcd_gotoxy(1, 1);       
       printf(lcd_putc, "\fRead these bytes\n");
       printf(lcd_putc, "from the 4 corners:\n\n");
       printf(lcd_putc, "     %c %c %c %c", b1, b2, b3, b4);       
       delay_ms(3000);
    #endif
    
       // Type some characters and backspace over them.
       printf(lcd_putc, "\fType characters and\n");
       printf(lcd_putc,   "backspace over them.");
       delay_ms(2000);
    
       // Go to end of 2nd line.
       lcd_gotoxy(20, 2);       
    
       // Backspace over 2nd line.
       for(i = 0; i < 20; i++)
          {
           printf(lcd_putc," \b\b");
           delay_ms(150);
          }
    
       // Go to end of first line.               
       lcd_gotoxy(20, 1);       
    
       // Backspace over first line.
       for(i = 0; i < 20; i++)
          {
           printf(lcd_putc," \b\b");
           delay_ms(150);
          }         
    
      }   
    }

    Mais le code ne fonctionne pas.
    J'ai donc modifié le init_lcd()
    pour y ajouter setfunction, display off , display clear, Entry mode set.

    Code:
    void lcd_init(void)
    {
    int8 i;
    
    lcd_line = 1;
    
    output_low(LCD_RS);
    
    #ifdef USE_RW_PIN
    output_low(LCD_RW);
    #endif
    
    output_low(LCD_E);
    
    // Some LCDs require 15 ms minimum delay after
    // power-up.  Others require 30 ms.  I'm going
    // to set it to 35 ms, so it should work with
    // all of them.
    delay_ms(35);         
    
    for(i=0 ;i < 3; i++)
       {
        lcd_send_nibble(0x03);
        delay_ms(5);
       }
    
    lcd_send_nibble(0x02);
        lcd_send_nibble(0b001010);      // setfunction
        delay_ms(5);
        lcd_send_nibble(0b00001000);   // display off
        delay_ms(5);
        lcd_send_nibble(0b00000001);   // display clear
        delay_ms(5);
        lcd_send_nibble(0b00000110);  // Entry mode set
        delay_ms(5);
    
    for(i=0; i < sizeof(LCD_INIT_STRING); i++)
       {
        lcd_send_byte(0, LCD_INIT_STRING[i]);
       
        // If the R/W signal is not used, then
        // the busy bit can't be polled.  One of
        // the init commands takes longer than
        // the hard-coded delay of 50 us, so in
        // that case, lets just do a 5 ms delay
        // after all four of them.
        #ifndef USE_RW_PIN
        delay_ms(5);
        #endif
       }
    
    }
    Le souci et que cela ne fonctionne pas.
    Le lcd reste impassible avec la 1er et 3eme ligne remplies de petits carrées (5x8) et la 2eme et 4 eme sont vides.

    Il s'agit du premier driver que j'utilise et j'ai du mal a tout comprendre .
    J'ai également tenté de réaliser un petit driver qui affiche la lettre A sur la ligne 1 case 1 du lcd sans suces non plus.

    Auriez vous une petits idées ?

    -----

  2. #2
    spown

    Re : Pic 18f2221 et lcd MC42003a6w

    Bonjour/bonsoir est bienvenue sur FUTURA;

    Est ce que le branchement des pins est le même que celui du code que t'as pris ?

  3. #3
    jb458

    Re : Pic 18f2221 et lcd MC42003a6w

    Oui j'ai effectué les modifications dans le driver

  4. #4
    jb458

    Re : Pic 18f2221 et lcd MC42003a6w

    J'ai essayé de simuler sur ISIS le programme et tout fonctionne (avec un lcd 4x20 generic ).
    Mon problème est forcement hardware.
    je n’arrête pas de scruter le datasheet du lcd mais rien à faire je ne trouve pas pourquoi il y a un problème.

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

    Re : Pic 18f2221 et lcd MC42003a6w

    J'ai trouvé d’où venait le problème .
    J'utilise une carte de développement qui s'appelle QL200.
    il y a un connecteur pour y brancher un lcd avec les indications rs, e, r/w, ... dessus de chaque broche du connecteur .
    Ces indications sont complétement fausses elles correspondent bien au lcd mais pas à la réalité du routage.

Discussions similaires

  1. temporisation ajustable avec un 18f2221
    Par dodge256 dans le forum Électronique
    Réponses: 10
    Dernier message: 07/09/2011, 17h54
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...