1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

XLCD with PIC18f452

Discussion in 'Microcontrollers' started by afnan.bashir, Apr 23, 2013.

  1. Angry Badger

    Angry Badger Member

    Joined:
    Jun 29, 2008
    Messages:
    201
    Likes:
    8
    Location:
    Flintshire, North Wales
    My mistake I think.
     
    Last edited: Apr 30, 2013
  2. Angry Badger

    Angry Badger Member

    Joined:
    Jun 29, 2008
    Messages:
    201
    Likes:
    8
    Location:
    Flintshire, North Wales
    Hi,

    That third party library appears to work.

    I made some very slight mods to suit my PIC18F2420...

    [​IMG]

    Code (text):
            #ifndef __HD44780_H
            #define __HD44780_H
             
            //******************************************
            //  Library for control LCD HD44780        *
            //  Mode Control 4 bits                    *
            //  By Hector                              *
            //  http://www.youtube.com/user/Hector8389 *
            //******************************************
             
            //#include <p18f452.h>     // Select your MCU
            #include <p18f2420.h>
            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>
            #include <delays.h>
             
            /////////////////////////////////////////////
            //                                         //
            // Configure your MCU. Any mode            //
            // Pin Set digital mode. your code         //
            //                                         //
            /////////////////////////////////////////////  
             
            #define LCD_RD7     LATBbits.LATB0      // D7    
            #define TRIS_RD7    TRISBbits.TRISB0    
             
            #define LCD_RD6     LATBbits.LATB1      // D6
            #define TRIS_RD6    TRISBbits.TRISB1
             
           #define LCD_RD5     LATBbits.LATB2      // D5
            #define TRIS_RD5    TRISBbits.TRISB2
             
            #define LCD_RD4     LATBbits.LATB3      // D4
            #define TRIS_RD4    TRISBbits.TRISB3
             
            #define LCD_EN     LATBbits.LATB4       // EN
            #define TRIS_EN    TRISBbits.TRISB4
             
            #define LCD_RS     LATBbits.LATB5       // RS
            #define TRIS_RS    TRISBbits.TRISB5
             
             
            /////////////////////////////////////////////
            //                                         //
            // Available Lcd Commands                  //
            //                                         //
            /////////////////////////////////////////////
             
            #define      LCD_FIRST_ROW           (128)
            #define      LCD_SECOND_ROW         (192)
            #define      LCD_THIRD_ROW           148
            #define      LCD_FOURTH_ROW          212
            #define      LCD_CLEAR               1
            #define      LCD_RETURN_HOME         2
            #define      LCD_CURSOR_OFF          12
            #define      LCD_UNDERLINE_ON        14
            #define      LCD_BLINK_CURSOR_ON     15
            #define      LCD_MOVE_CURSOR_LEFT    16
            #define      LCD_MOVE_CURSOR_RIGHT   20
            #define      LCD_TURN_OFF            0
            #define      LCD_TURN_ON             8
            #define      LCD_SHIFT_LEFT          24
            #define      LCD_SHIFT_RIGHT         28
           
           
           
           
            void Lcd_Init(void);
           
            //void Lcd_Out(unsigned char y, unsigned char x, const rom char *buffer);
           
            void Lcd_Out(unsigned char y, unsigned char x, const char *buffer);
           
            void Lcd_Out2(unsigned char y, unsigned char x, char *buffer);
            void Lcd_Chr_CP(char data);
            void Lcd_Cmd(unsigned char Cmd);
             
            void Delay_5us(void);
            void Delay_5500us(void);
             
             
            /////////////////////////////////////////////
            //                                         //
            // Set delays, based on the                //
            // frequency of a XTAL.                    //
            //                                         //
            /////////////////////////////////////////////
             
            void Delay_5us(void){
            // Delay of 5us
            // Cycles = (5us * 20MHz) / 4
            // Cycles = 25
            // Put 25 more  
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
            Nop(); Nop(); Nop(); Nop(); Nop();
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
            Nop(); Nop(); Nop(); Nop(); Nop();
             
            }
             
            void Delay_5500us(void){
            // Delay of 5.5ms
            // Cycles = (5.5ms * 20MHz) / 4
            // Cycles = 27,500 = 28,000
            Delay1KTCYx(28);
            }
             
             
            void Lcd_Init(void){
            unsigned char data;
           
           
             
            TRIS_RD7 = 0; TRIS_RD6 = 0; TRIS_RD5 = 0; TRIS_RD4 = 0; TRIS_EN = 0; TRIS_RS = 0;
            LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 0; LCD_RD4 = 0; LCD_EN = 0; LCD_RS = 0;
             
           
            //  167mS
            Delay_5500us(); Delay_5500us(); Delay_5500us();
            Delay_5500us(); Delay_5500us(); Delay_5500us();
           
             
            for(data = 1; data < 4; data ++)
            {
                LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 1; LCD_EN = 0; LCD_RS = 0;
                LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 1; LCD_EN = 1; LCD_RS = 0;
                Delay_5us();
                LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 1; LCD_EN = 0; LCD_RS = 0;
                Delay_5500us();
            }
            LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 0; LCD_EN = 0; LCD_RS = 0;
            LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 0; LCD_EN = 1; LCD_RS = 0;
            Delay_5us();
            LCD_RD7 = 0; LCD_RD6 = 0; LCD_RD5 = 1; LCD_RD4 = 0; LCD_EN = 0; LCD_RS = 0;
            Delay_5500us();
             
            data = 40; Lcd_Cmd(data);
            data = 16; Lcd_Cmd(data);
            data = 1;  Lcd_Cmd(data);
            data = 15; Lcd_Cmd(data);
            }
             
             
            //void Lcd_Out(unsigned char y, unsigned char x, const rom char *buffer)
           
            void Lcd_Out(unsigned char y, unsigned char x, const char *buffer)
            {
            unsigned char data;
             
            switch (y)
            {
                case 1:
                data = 128 + x;
                break;
                case 2:
                data = 192 + x;
                break;
                case 3:
                data = 148 + x;
                break;
                case 4:
                data = 212 + x;
                break;
                default:
                break;
            }
             
            Lcd_Cmd(data);
             
            while(*buffer)              // Write data to LCD up to null
            {                
                Lcd_Chr_CP(*buffer);
                buffer++;               // Increment buffer
            }
            return;
            }
             
             
             
             
            void Lcd_Out2(unsigned char y, unsigned char x, char *buffer)
            {
            unsigned char data;
            switch (y)
            {
                case 1:
                data = 128 + x;
                break;
                case 2:
                data = 192 + x;
                break;
                case 3:
                data = 148 + x;
                break;
                case 4:
                data = 212 + x;
                break;
                default:
                break;
            }
             
            Lcd_Cmd(data);
             
            while(*buffer)              // Write data to LCD up to null
            {                
                Lcd_Chr_CP(*buffer);
                buffer++;               // Increment buffer
            }
            return;
            }
             
            void Lcd_Chr_CP(char data){
            LCD_EN = 0; LCD_RS = 1;
            LCD_RD7 = (data & 0b10000000)>>7; LCD_RD6 = (data & 0b01000000)>>6;
            LCD_RD5 = (data & 0b00100000)>>5; LCD_RD4 = (data & 0b00010000)>>4;
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
            LCD_EN = 1; Delay_5us(); LCD_EN = 0;
             
            LCD_RD7 = (data & 0b00001000)>>3; LCD_RD6 = (data & 0b00000100)>>2;
            LCD_RD5 = (data & 0b00000010)>>1; LCD_RD4 = (data & 0b00000001);
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();  
            LCD_EN = 1; Delay_5us(); LCD_EN = 0;
            Delay_5us(); Delay_5500us();
            }
             
            void Lcd_Cmd(unsigned char Cmd){
            unsigned char data;
            data = Cmd;
            LCD_EN = 0; LCD_RS = 0;
            LCD_RD7 = (data & 0b10000000)>>7; LCD_RD6 = (data & 0b01000000)>>6;
            LCD_RD5 = (data & 0b00100000)>>5; LCD_RD4 = (data & 0b00010000)>>4;
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();  
            LCD_EN = 1; Delay_5us(); LCD_EN = 0;
             
            LCD_RD7 = (data & 0b00001000)>>3; LCD_RD6 = (data & 0b00000100)>>2;
            LCD_RD5 = (data & 0b00000010)>>1; LCD_RD4 = (data & 0b00000001);
            Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();  
            LCD_EN = 1; Delay_5us(); LCD_EN = 0;
            Delay_5500us();//Delay_5us();
            }
            #endif
     
    Code (text):
    #include <p18f2420.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "hd44780.h"
    //#include "my_delays.h"
    #include <delays.h>
     
    #include <xc.h>

    /*------------------------------------------------------------------------*/
    //THESE ARE CONFIG WORDS FOR A 2420!
     
    #pragma config CONFIG1H = 0X08;
    #pragma config CONFIG2L = 0X19;
    #pragma config CONFIG2H = 0X1E;
    #pragma config CONFIG3H = 0X01; // MCLRE ON = 0x81, OFF = 0x01
    #pragma config CONFIG4L = 0X80;
     

    /*------------------------------------------------------------------------*/
     
    #define _XTAL_FREQ (4000000)
     
    void main(void)
    {
        OSCCON = 0b01100010;            // Fosc = 4MHz (Inst. clk = 1MHz)
        ADCON1 = 0xF;                   // No analog, all digital i/o
        TRISA = 0x00;
        TRISB = 0x0;
        TRISC = 0x0;
        LATB = 0x0;
        Lcd_Init();

        Lcd_Cmd(LCD_CLEAR);
        Lcd_Cmd(LCD_CURSOR_OFF);
     
        /******************** ADC Initilization ***********************************/
         //ADCON1 = 0x80;                          // Configure analog inputs and Vref
         //TRISA = 0xFF;  
     
     
        //Delay_ms(100);
        __delay_ms(100);

        while(1)
        {
            Lcd_Out(1, 1, "Free download");
            //Delay_ms(500);
       
            while(1);
       
        }
    }
     
     
  3. Angry Badger

    Angry Badger Member

    Joined:
    Jun 29, 2008
    Messages:
    201
    Likes:
    8
    Location:
    Flintshire, North Wales
    Hi,

    Looking at you original schematic I now realise that you are not using the LCD busy flag.

    The code I posted in post #15 does require the use of the busy flag i.e. you have to have LCD pin 5 connected. Hope that didn't cause you any confusion (I expect it has though!).

    Don't despair :) you'll get there in the end.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,157
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE

    Afnan.... One or two little issues


    Your DATAPORT is backwards RB0 goes to D7.....

    Secondly the LCDTYPE is not selecting two lines..

    Thirdly you do not need to add the line OSCCON =??? as you are setting HS XTAL...

    Lastly your redeclaration of XTAL FREQ is different from the first... One is 8Mhz and the other is 4Mhz

    Once you change your dataport it will work...
     
  6. afnan.bashir

    afnan.bashir Member

    Joined:
    Mar 15, 2013
    Messages:
    31
    Likes:
    0
    Even Changing Port direction and adding 0x28 inplace of lcd_type does not makes it work
     
  7. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,157
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    LCDTYPE = 0x2C....

    I have your code... AND your schematic running in ISIS....
     
  8. afnan.bashir

    afnan.bashir Member

    Joined:
    Mar 15, 2013
    Messages:
    31
    Likes:
    0
    Surely do not know what is going on. I have same files as Angry Badger. I just changed 0x2C in main file. But still nothing on lcd in ISIS. Can you send me your Project and Hex file so i can make sure that compiler is not playing tricks here at my side.
    Here is the modified main.c
    Code (text):
    #include <xc.h>
    #include "My_xlcd.h"
    /*------------------------------------------------------------------------*/


    // CONFIG1H
    #pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
    #pragma config OSCS = OFF       // Oscillator System Clock Switch Enable bit (Oscillator system clock switch option is disabled (main oscillator is source))

    // CONFIG2L
    #pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
    #pragma config BOR = ON         // Brown-out Reset Enable bit (Brown-out Reset enabled)
    #pragma config BORV = 20        // Brown-out Reset Voltage bits (VBOR set to 2.0V)

    // CONFIG2H
    #pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
    #pragma config WDTPS = 128      // Watchdog Timer Postscale Select bits (1:128)

    // CONFIG3H
    #pragma config CCP2MUX = ON     // CCP2 Mux bit (CCP2 input/output is multiplexed with RC1)

    // CONFIG4L
    #pragma config STVR = ON        // Stack Full/Underflow Reset Enable bit (Stack Full/Underflow will cause RESET)
    #pragma config LVP = ON         // Low Voltage ICSP Enable bit (Low Voltage ICSP enabled)

    // CONFIG5L
    #pragma config CP0 = OFF        // Code Protection bit (Block 0 (000200-001FFFh) not code protected)
    #pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code protected)
    #pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code protected)
    #pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code protected)

    // CONFIG5H
    #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code protected)
    #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code protected)

    // CONFIG6L
    #pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000200-001FFFh) not write protected)
    #pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write protected)
    #pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write protected)
    #pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write protected)

    // CONFIG6H
    #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write protected)
    #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write protected)
    #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write protected)

    // CONFIG7L
    #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000200-001FFFh) not protected from Table Reads executed in other blocks)
    #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from Table Reads executed in other blocks)
    #pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from Table Reads executed in other blocks)
    #pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from Table Reads executed in other blocks)

    // CONFIG7H
    #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from Table Reads executed in other blocks)
     
     
    /*------------------------------------------------------------------------*/
     
    #define _XTAL_FREQ (8000000)    /* Not using xtal, only to make delays work as
                                        it won't compile without this */
     
     
    void DelayFor18TCY(void);
    void DelayPORXLCD(void);
    void DelayXLCD(void);
     
    /*------------------------------------------------------------------------*/
     
    void main (void)
    {
        ADCON1 = 0xF;                   // No analog, all digital i/o
        TRISA = 0x00;
        TRISB = 0x0;
        TRISC = 0x0;
        LATB = 0x0;
     
     
    while(1)
    {
     
        OpenXLCD(0x2C);
        while(BusyXLCD());
     
        WriteCmdXLCD(SHIFT_DISP_LEFT);
        while(BusyXLCD());
     
        WriteDataXLCD('A');
        while(BusyXLCD());
     
        WriteDataXLCD('t');
        while(BusyXLCD());
     
        WriteDataXLCD(' ');
        while(BusyXLCD());
     
        putrsXLCD( "last! XLCD," );
        while(BusyXLCD());
     
        WriteCmdXLCD(0xC0);
        while(BusyXLCD());
     
        putrsXLCD( "thanks Ian" );
        while(BusyXLCD());
     
        while(1);
     
        }
     
     }
    /*------------------------------------------------------------------------*/
    void DelayFor18TCY(void)
    {
        __delay_us(18);
     
        }
     
    /*------------------------------------------------------------------------*/
    void DelayPORXLCD(void)
    {
         __delay_ms(15);
     
        }
    /*------------------------------------------------------------------------*/
    void DelayXLCD(void)
    {
        __delay_ms(5);
     
        }
    /*------------------------------------------------------------------------*/
     
  9. afnan.bashir

    afnan.bashir Member

    Joined:
    Mar 15, 2013
    Messages:
    31
    Likes:
    0
    After changing the ports in reverse direction
    RB0->D4
    RB1->D5
    RB2->D6
    RB3->D7

    RB4 ->RS
    RB5->EN
    RB6->RW

    with above these it still did not worked. I also tried to do one more thing that copied files(XLCD folder with all C and lcd.h file too) to project directory. On ISIS i got some warnings as shown in image


    I wonder why am i so unlucky..........
     

    Attached Files:

  10. afnan.bashir

    afnan.bashir Member

    Joined:
    Mar 15, 2013
    Messages:
    31
    Likes:
    0
    I Also Managed to run another opensource library. It showed perfect output at ISIS. When i write it to controller it does not show anything just straight boxes. Ofcourse this means that lcd is not initialized or something. It points that something is wrong with the hardware right? but No, Why? because of following reasons
    1. With LCD i also toggle ports and thy do toggle.
    2. Checked Connections multiple time with connectivity meter too
    3. I wrote simple lcd test program at same pin connections it works like charm(Just ground the RW pin of LCD) .


    The confusion is if the Proteus is showing the correct working LCD program it should replicate on hardware. What are my possible directions to dig into this issue? Ofcourse this is debugging but i have done what i knew you guys may help me debugging.

    Following are codes for


    Code (text):
    // LCD module connections
    sbit LCD_RS at RB5_bit;
    sbit LCD_EN at RB4_bit;
    sbit LCD_D4 at RB0_bit;
    sbit LCD_D5 at RB1_bit;
    sbit LCD_D6 at RB2_bit;
    sbit LCD_D7 at RB3_bit;

    sbit LCD_RS_Direction at TRISB5_bit;
    sbit LCD_EN_Direction at TRISB4_bit;
    sbit LCD_D4_Direction at TRISB0_bit;
    sbit LCD_D5_Direction at TRISB1_bit;
    sbit LCD_D6_Direction at TRISB2_bit;
    sbit LCD_D7_Direction at TRISB3_bit;
    // End LCD module connections

    const char txt1[] = "A";
    const char txt2[] = "B";
    const char txt3[] = "C";
    const char txt4[] = "D";
          char i;                              // Loop variable
    char  array[6];

    void Move_Delay() {                  // Function used for text moving
      Delay_ms(500);                     // You can change the moving speed here
    }
    void main() {

              PORTD = 0x00;
              TRISD = 0x00;

      Lcd_Init();                        // Initialize LCD

      Lcd_Cmd(_LCD_CLEAR);               // Clear display
      Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
       while(1)
       {
                   Lcd_Out(1,1,"EEPROM Test");
                   PORTD = ~PORTD;

           Delay_ms(2000);
           
       }

    }

    lcd.c
    Code (text):
    /********************************************************************

    16X2 ALPHANEUMERIC LCD INTERFACING LIBRARY FOR PIC 18F MCUS
    -----------------------------------------------------------

    Easy to use library for interfacing 16x2 lcd in 4 bit mode.
    MCU: PIC18FXXXX Series from Microchip.
    Compiler: HI-TECH C Compiler for PIC18 MCUs (http://www.htsoft.com/)

    Copyrights 2008-2009 Avinash Gupta
    eXtreme Electronics, India

    For More Info visit
    http://www.eXtremeElectronics.co.in

    Mail: me@avinashgupta.com

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

    #include <p18f452.h>

    #include "lcd.h"


    #define LCD_DATA_LAT    LAT(LCD_DATA)
    #define LCD_E_LAT       LAT(LCD_E)
    #define LCD_RS_LAT      LAT(LCD_RS)
    #define LCD_RW_LAT      LAT(LCD_RW)

    #define LCD_DATA_TRIS   TRIS(LCD_DATA)
    #define LCD_E_TRIS      TRIS(LCD_E)
    #define LCD_RS_TRIS     TRIS(LCD_RS)
    #define LCD_RW_TRIS     TRIS(LCD_RW)

    #define LCD_DATA_PORT   PORT(LCD_DATA)

    #define SET_E() (LCD_E_LAT|=(1<<LCD_E_POS))
    #define SET_RS() (LCD_RS_LAT|=(1<<LCD_RS_POS))
    #define SET_RW() (LCD_RW_LAT|=(1<<LCD_RW_POS))

    #define CLEAR_E() (LCD_E_LAT&=(~(1<<LCD_E_POS)))
    #define CLEAR_RS() (LCD_RS_LAT&=(~(1<<LCD_RS_POS)))
    #define CLEAR_RW() (LCD_RW_LAT&=(~(1<<LCD_RW_POS)))




    void LCDByte(uint8_t c,uint8_t isdata)
    {
    //Sends a byte to the LCD in 4bit mode
    //cmd=0 for data
    //cmd=1 for command


    //NOTE: THIS FUNCTION RETURS ONLY WHEN LCD HAS PROCESSED THE COMMAND

    uint8_t hn,ln;          //Nibbles
    uint8_t temp;

    hn=c>>4;
    ln=(c & 0x0F);

    if(isdata==0)
        CLEAR_RS();
    else
        SET_RS();

    __delay_us(0.500);      //tAS

    SET_E();

    //Send high nibble

    temp=(LCD_DATA_LAT & 0XF0)|(hn);
    LCD_DATA_LAT=temp;

    __delay_us(1);          //tEH

    //Now data lines are stable pull E low for transmission

    CLEAR_E();

    __delay_us(1);

    //Send the lower nibble
    SET_E();

    temp=(LCD_DATA_LAT & 0XF0)|(ln);

    LCD_DATA_LAT=temp;

    __delay_us(1);          //tEH

    //SEND

    CLEAR_E();

    __delay_us(1);          //tEL

    LCDBusyLoop();
    }

    void LCDBusyLoop()
    {
        //This function waits till lcd is BUSY

        uint8_t busy,status=0x00,temp;

        //Change Port to input type because we are reading data
        LCD_DATA_TRIS|=0x0F;

        //change LCD mode
        SET_RW();       //Read mode
        CLEAR_RS();     //Read status

        //Let the RW/RS lines stabilize

        __delay_us(0.5);        //tAS

       
        do
        {

            SET_E();

            //Wait tDA for data to become available
            __delay_us(0.5);

            status=LCD_DATA_PORT;
            status=status<<4;

            __delay_us(0.5);

            //Pull E low
            CLEAR_E();
            __delay_us(1);  //tEL

            SET_E();
            __delay_us(0.5);

            temp=LCD_DATA_PORT;
            temp&=0x0F;

            status=status|temp;

            busy=status & 0b10000000;

            __delay_us(0.5);
            CLEAR_E();
            __delay_us(1);  //tEL
        }while(busy);

        CLEAR_RW();     //write mode
        //Change Port to output
        LCD_DATA_TRIS&=0xF0;

    }

    void LCDInit(uint8_t style)
    {
        /*****************************************************************
       
        This function Initializes the lcd module
        must be called before calling lcd related functions

        Arguments:
        style = LS_BLINK,LS_ULINE(can be "OR"ed for combination)
        LS_BLINK :The cursor is blinking type
        LS_ULINE :Cursor is "underline" type else "block" type

        *****************************************************************/
       
        //After power on Wait for LCD to Initialize
        __delay_ms(30);
       
        //Set IO Ports
        LCD_DATA_TRIS&=(0xF0);
        LCD_E_TRIS&=(~(1<<LCD_E_POS));
        LCD_RS_TRIS&=(~(1<<LCD_RS_POS));
        LCD_RW_TRIS&=(~(1<<LCD_RW_POS));

        LCD_DATA_LAT&=0XF0;
        CLEAR_E();
        CLEAR_RW();
        CLEAR_RS();

        //Set 4-bit mode
        __delay_us(0.3);    //tAS

        SET_E();
        LCD_DATA_LAT|=(0b00000010); //[B] To transfer 0b00100000 i was using LCD_DATA_PORT|=0b00100000
        __delay_us(1);
        CLEAR_E();
        __delay_us(1);
       
        //Wait for LCD to execute the Functionset Command
        LCDBusyLoop();                                    //[B] Forgot this delay

        //Now the LCD is in 4-bit mode

        LCDCmd(0b00001100|style);   //Display On
        LCDCmd(0b00101000);         //function set 4-bit,2 line 5x7 dot format
    }
    void LCDWriteString(const char *msg)
    {
        /*****************************************************************
       
        This function Writes a given string to lcd at the current cursor
        location.

        Arguments:
        msg: a null terminated string to print


        *****************************************************************/
     while(*msg!='\0')
     {
        LCDData(*msg);
        msg++;
     }
    }

    void LCDWriteInt(int val,unsigned int field_length)
    {
        /***************************************************************
        This function writes a integer type value to LCD module

        Arguments:
        1)int val   : Value to print

        2)unsigned int field_length :total length of field in which the value is printed
        must be between 1-5 if it is -1 the field length is no of digits in the val

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

        char str[5]={0,0,0,0,0};
        int i=4,j=0;
        while(val)
        {
        str[i]=val%10;
        val=val/10;
        i--;
        }
        if(field_length==-1)
            while(str[j]==0) j++;
        else
            j=5-field_length;

        if(val<0) LCDData('-');
        for(i=j;i<5;i++)
        {
        LCDData(48+str[i]);
        }
    }
    void LCDGotoXY(uint8_t x,uint8_t y)
    {
     if(x<40)
     {
      if(y) x|=0b01000000;
      x|=0b10000000;
      LCDCmd(x);
      }
    }
     
    main.c
    Code (text):
    /********************************************************************

    16X2 ALPHANEUMERIC LCD INTERFACING LIBRARY TEST PROGRAM
    ---------------------------------------------------------

    A testing program for our LCD library.

    Easy to use library for interfacing 16x2 lcd in 4 bit mode.
    MCU: PIC18FXXXX Series from Microchip.
    Compiler: HI-TECH C Compiler for PIC18 MCUs (http://www.htsoft.com/)

    Copyrights 2008-2009 Avinash Gupta
    eXtreme Electronics, India

    For More Info visit
    http://www.eXtremeElectronics.co.in

    Mail: me@avinashgupta.com

    ********************************************************************/
    #include <xc.h>
    #include <p18f452.h>

    #include "lcd.h"

    // CONFIG1H
    #pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
    #pragma config OSCS = OFF       // Oscillator System Clock Switch Enable bit (Oscillator system clock switch option is disabled (main oscillator is source))

    // CONFIG2L
    #pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
    #pragma config BOR = ON         // Brown-out Reset Enable bit (Brown-out Reset enabled)
    #pragma config BORV = 20        // Brown-out Reset Voltage bits (VBOR set to 2.0V)

    // CONFIG2H
    #pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
    #pragma config WDTPS = 128      // Watchdog Timer Postscale Select bits (1:128)

    // CONFIG3H
    #pragma config CCP2MUX = ON     // CCP2 Mux bit (CCP2 input/output is multiplexed with RC1)

    // CONFIG4L
    #pragma config STVR = ON        // Stack Full/Underflow Reset Enable bit (Stack Full/Underflow will cause RESET)
    #pragma config LVP = ON         // Low Voltage ICSP Enable bit (Low Voltage ICSP enabled)

    // CONFIG5L
    #pragma config CP0 = OFF        // Code Protection bit (Block 0 (000200-001FFFh) not code protected)
    #pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code protected)
    #pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code protected)
    #pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code protected)

    // CONFIG5H
    #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code protected)
    #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code protected)

    // CONFIG6L
    #pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000200-001FFFh) not write protected)
    #pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write protected)
    #pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write protected)
    #pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write protected)

    // CONFIG6H
    #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write protected)
    #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write protected)
    #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write protected)

    // CONFIG7L
    #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000200-001FFFh) not protected from Table Reads executed in other blocks)
    #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from Table Reads executed in other blocks)
    #pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from Table Reads executed in other blocks)
    #pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from Table Reads executed in other blocks)

    // CONFIG7H
    #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from Table Reads executed in other blocks)
     

    //Simple Delay Routine
    void Wait(unsigned int delay)
    {
        for(;delay;delay--)
            __delay_us(100);
    }

    void main()
    {
        //Let the Module start up
        Wait(100);
            PORTD = 0x00;
            TRISD = 0x00;

        //Initialize the LCD Module
        LCDInit(LS_BLINK);

        //Clear the Module
        LCDClear();
       
        //Write a string at current cursor pos
        LCDWriteString("**** Yeh!!");

        Wait(20000);

        //Now Clear the display
        LCDClear();

        LCDWriteString("God Bless all !!");

        //Goto POS (X=0,Y=1 i.e. Line 2)
        //And Write a string
        LCDWriteStringXY(5,1,"<**************>");

        Wait(20000);

        //Write Some Numbers
        for(char i=0;i<100;i++)
        {
                LCDClear();
                LCDWriteInt(i,3);
                Wait(3000);
        }
       
        LCDClear();
        LCDWriteString("    The  End    ");

        //Loop Forever
        while(1)
            {
                PORTD = ~PORTD;
            }

       
    }
    lcd.h
    Code (text):
    /********************************************************************

    16X2 ALPHANEUMERIC LCD INTERFACING LIBRARY FOR PIC 18F MCUS
    -----------------------------------------------------------
    ********************************************************************/
    #include <p18f452.h>
    #define _XTAL_FREQ 8000000UL
    #include "myutils.h"

    #ifndef _LCD_H
    #define _LCD_H

    typedef unsigned char uint8_t;

    /*_________________________________________________________________________________________*/

    /************************************************
        LCD CONNECTIONS
    *************************************************/

    #define LCD_DATA B  //Port PD0-PD3 are connected to D4-D7

    #define LCD_E B     //Enable/strobe signal
    #define LCD_E_POS   4   //Position of enable in above port

    #define LCD_RS B
    #define LCD_RS_POS 5

    #define LCD_RW B
    #define LCD_RW_POS 6


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

    #define LS_BLINK 0B00000001
    #define LS_ULINE 0B00000010



    /***************************************************
                F U N C T I O N S
    ****************************************************/

    void LCDInit(uint8_t style);
    void LCDWriteString(const char *msg);
    void LCDWriteInt(int val,unsigned int field_length);
    void LCDGotoXY(uint8_t x,uint8_t y);

    //Low level
    void LCDByte(uint8_t,uint8_t);
    #define LCDCmd(c) (LCDByte(c,0))
    #define LCDData(d) (LCDByte(d,1))

    void LCDBusyLoop();



    /***************************************************
            F U N C T I O N S     E N D
    ****************************************************/


    /***************************************************
        M A C R O S
    ***************************************************/
    #define LCDClear() LCDCmd(0b00000001)
    #define LCDHome() LCDCmd(0b00000010)

    #define LCDWriteStringXY(x,y,msg) {\
     LCDGotoXY(x,y);\
     LCDWriteString(msg);\
    }

    #define LCDWriteIntXY(x,y,val,fl) {\
     LCDGotoXY(x,y);\
     LCDWriteInt(val,fl);\
    }
    /***************************************************/




    /*_________________________________________________________________________________________*/
    #endif
     
    Guys i really need your help
     
  11. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,157
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    Afnan.... here is ISIS running the code YOU posted

    Capture.png

    The only change is here..

    Capture.png
     
  12. Angry Badger

    Angry Badger Member

    Joined:
    Jun 29, 2008
    Messages:
    201
    Likes:
    8
    Location:
    Flintshire, North Wales
    Hi Afnan & Ian,

    Could we just clarify something? Afnan, is your hardware circuit exactly as shown in that schematic in your very first post?

    If it is then you have to be sure to use code that does not check for the state of the LCD busy flag. The code should use a delay instead.

    Alternatively connect your circuit as shown in the schematic in Ian's last post.

    For what it's worth, I built another little circuit using a PIC18F4520 which is to all intents and purposes the same chip you are using, except this one can run of an internal oscillator. I again used the third party code you provided in post #17 (because this code works without polling the LCD busy flag). Additionally a 'pot is used to adjust the LCD contrast.

    Don't go searching for more third party library's, all the code you require is already here in this thread. :)

    I sincerely apologise for spelling your name incorrectly! It's late now, I've been up since 0430, been and done a b*****d 12 hour shift and just want to go to bed now - so not going to retake the photo :D

    [​IMG]

    Code (text):
    #include <p18f4520.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "hd44780.h"
    //#include "my_delays.h"
    #include <delays.h>
     
    #include <xc.h>

    /*------------------------------------------------------------------------*/
    //THESE ARE CONFIG WORDS FOR A 4520!

    #pragma config CONFIG1H = 0X08;
    #pragma config CONFIG2L = 0X19;
    #pragma config CONFIG2H = 0X1E;
    #pragma config CONFIG3H = 0X01; // MCLRE ON = 0x81, OFF = 0x01
    #pragma config CONFIG4L = 0X80;


    /*------------------------------------------------------------------------*/
     
    #define _XTAL_FREQ (4000000)    // SET THIS TO SUIT YOUR FREQUENCY
     
    void main(void)
    {
        OSCCON = 0b01100010;            // Fosc = 4MHz (Inst. clk = 1MHz)
        ADCON1 = 0xF;                   // No analog, all digital i/o
        TRISA = 0x00;
        TRISB = 0x0;
        TRISC = 0x0;
        LATB = 0x0;

        Lcd_Init();
        Lcd_Cmd(LCD_CLEAR);
        Lcd_Cmd(LCD_CURSOR_OFF);
     
    /*--------------------------------------------------------------------------*/
    while(1)

        //__delay_ms(100);

        {
            Lcd_Out(1, 1, "Hi Afran");

            while(1);

        }
    }
     
     
  13. afnan.bashir

    afnan.bashir Member

    Joined:
    Mar 15, 2013
    Messages:
    31
    Likes:
    0
    Thank you for doing the code for me you are great person because no one can do that long shift of work i suppose. Well the circuit is as follows

    RB0->D4
    RB1->D5
    RB2->D6
    RB3->D7

    RB4 ->RS
    RB5->EN
    RB6->RW

    The problem is that i am sure there is nothing wrong with the code. The same exact code (replacing delays with Delay_ms and us respectively) in mikroC gives perfect output at ISIS and Hardware where as compiling the code at MPLAB 8.9 with XC8 compiler gives the hex that runs only on ISIS.

    I am a bit confused now. I have been struggling for it more than two weeks
     
  14. superkai

    superkai New Member

    Joined:
    Jan 5, 2009
    Messages:
    1
    Likes:
    0
    Thank you. Your code inside HD44780.h are work with MY PIC18F1320 8MHz on EasyPIC5 board.
     
  15. Quintino

    Quintino New Member

    Joined:
    May 1, 2014
    Messages:
    4
    Likes:
    0
    Dear Angry Badger,
    I have just tried your code on post #15 by using a PIC18F4685 with XC8 compiler, however I can only see the first line "At last! XLCD,".
    The second line is empty.
    In the code I can see that you use 0xC0 to change line and then you write "thanks Ian".
    I believe my hardware configuration is correct.
    Does anyone know what should be the problem here?
     
  16. atferrari

    atferrari Well-Known Member

    Joined:
    Oct 8, 2003
    Messages:
    2,811
    Likes:
    121
    Location:
    Buenos Aires - Argentina
    Portability Ian? What is that?

    Wondering what could be wading through all this ....:(..................................................:arghh:
     
  17. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,157
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    Quintino Have you enabled two line in the Init section, Or are you using the XLCD library?

    Portability on micro's.... I wish!!!
     
  18. Quintino

    Quintino New Member

    Joined:
    May 1, 2014
    Messages:
    4
    Likes:
    0
    Dear Ian, thank you for your help.

    I am using the code that Angry Badger just posted with 3 files: XLCD Main.c My_XLCD.c and My.clcd.h.

    By adding these files to a new project I just programmed my PIC and that's it. Should I change something? I did not found any option to activate a second line. Could you please guide me through?
     
  19. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,157
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    Angry Badger hasn't posted XLCD routines... These are the built in routines... The routines above are written ( I suppose ) by him..

    Can you post me a schematic and you code, Then I can see what's going wrong..
     
  20. Quintino

    Quintino New Member

    Joined:
    May 1, 2014
    Messages:
    4
    Likes:
    0
    Dear Ian,
    I am sending you the complete project in MPLab X. I hope you can help me.
    Best regards.
     

    Attached Files:

  21. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,157
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    Ok!! I opened the project and ran it!!!! What do you need it to do? Seems okay to me!
     

Share This Page