Interfacing LCD with PIC Microcontroller – MPLAB XC8

Interfacing LCD with PIC Microcontroller – MPLAB XC8

In this tutorial we will see How to Interface a 16×2 character LCD module with PIC 16F877A Microcontroller using MPLAB X IDE and MPLAB XC8 C Compiler. 16×2 Character LCD is a very basic and low cost LCD module which is commonly used in electronic products and projects. 16×2 means it contains 2 rows that can display 16 characters. Its other variants such as 16×1 and 16×4 are also available in the market. In these displays, each character is displayed using 5×8 or 5×10 dot matrix.

For controlling LCD using MPLAB XC8 compiler we need to know the hardware of LCD. These LCDs commonly uses HD44780 compliant controllers. So we need to learn HD44780 Dot Matrix LCD Controller Datasheet. Don’t worry we already developed an LCD library including commonly used functions, so you can use it without any hardware knowledge of LCD.

16x2 LCD Pin Diagram

16×2 LCD Pin Diagram

First two pins GND and VCC (VSS and VDD) are for providing power to LCD display. 3ed pin VEE is used to control the contrast of the LCD display. A 10KΩ preset whose fixed ends connected to VDD, VSS and variable end connected to VEE can be used to control contrast of the LCD. A microcontroller or microprocessor need to send 2 types of information for operating this LCD Module, Data Information and Command Information. Data Information is the ASCII value of the characters to be displayed in the LCD screen and Command Information determines other operations such as position to be displayed, clear screen, shift etc. Data and Command Information are send to LCD through same data lines (DB0 – DB7) which are multiplexed using RS (Register Select) pin of LCD. When RS is HIGH LCD treats DB0 – DB7 data pins information as Data to be displayed and when it is LOW LCD treats it as Command Information. Enable (E) input of the LCD is used to give Data Strobe. HIGH (5V) Voltage Level in the Enable (E) pin tells the LCD that DB0 – DB7 contains valid information. The input signal R/W (Read or Write) determines whether data is written to or read from the LCD. In normal cases we need only writing hence it is tied to GROUND in circuit shown below.

The interface between this LCD and Microcontroller can be 8 bit or 4 bit and the difference between them is in how the data or commands are send to LCD. In the 8 bit mode, 8 bit data and commands are send through the data lines DB0 – DB7 and data strobe is given through E input of the LCD. But 4 bit mode uses only 4 data lines. In this 8 bit data and commands are splitted into 2 parts (4 bits each) and are sent sequentially through data lines DB4 – DB7 with its own data strobe through E input. The idea of 4 bit communication is introduced to save pins of a microcontroller. You may think that 4 bit mode will be slower than 8 bit. But the speed difference is only minimal. As LCDs are slow speed devices, the tiny speed difference between these modes is not significant. Just remember that microcontroller is operating at high speed in the range of MHz and we are viewing LCD with our eyes. Due to Persistence of Vision of our eyes we will not even feel the speed difference.


Hope that you got rough idea about how this LCD Module works. Actually you need to read the datasheet of HD44780 LCD driver used in this LCD Module to write a MPLAB XC8 program for PIC. But we solved this problem by creating a header file lcd.h which includes all the commonly used functions using 4 bit mode. Just include it and enjoy.

Circuit Diagram

Interfacing LCD with PIC Microcontroller - Circuit Diagram

Interfacing LCD with PIC Microcontroller – Circuit Diagram

LCD Library

  • Lcd_Init() : This function will initialize the LCD Module connected to the following defined pins.
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7

These connections must be defined for the proper working of LCD.

  • Lcd_Clear() : To clear the display.
  • Lcd_Set_Cursor(int row, int column) : This function is used to set row and column of the cursor on the LCD screen. By using this function we can change the position of the character or string displayed by following functions.
  • Lcd_Write_Char(char) : To write a character to LCD on the current position.
  • Lcd_Write_String(char *string) : To write string to LCD on the current position.
  • Lcd_Shift_Right() : To shift contents on the LCD screen Right once without changing the data in the Display RAM.
  • Lcd_Shift_Left() : To shift contents on the LCD screen Left once without changing the data in the Display RAM.

Note : The Pins to which LCD is connecting should be configured as Output Pins by writing to TRIS Register.

MPLAB XC8 Code

#define _XTAL_FREQ 8000000

#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7

#include <xc.h>
#include "lcd.h";

// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//END CONFIG

int main()
{
    unsigned int a;
    TRISD = 0x00;
    Lcd_Init();
    while(1)
    {
        Lcd_Clear();
        Lcd_Set_Cursor(1,1);
        Lcd_Write_String("LCD Library for");
        Lcd_Set_Cursor(2,1);
        Lcd_Write_String("MPLAB XC8");
        __delay_ms(2000);
        Lcd_Clear();
        Lcd_Set_Cursor(1,1);
        Lcd_Write_String("Developed By");
        Lcd_Set_Cursor(2,1);
        Lcd_Write_String("electroSome");
        __delay_ms(2000);
        Lcd_Clear();
        Lcd_Set_Cursor(1,1);
        Lcd_Write_String("www.electroSome.com");

        for(a=0;a<15;a++)
        {
            __delay_ms(300);
            Lcd_Shift_Left();
        }

        for(a=0;a<15;a++)
        {
            __delay_ms(300);
            Lcd_Shift_Right();
        }

        Lcd_Clear();
        Lcd_Set_Cursor(2,1);
        Lcd_Write_Char('e');
        Lcd_Write_Char('S');
        __delay_ms(2000);
    }
    return 0;
}

sprintf() to Format Outputs

sprintf() can be used to write formatted string to a variable. It can be used with this LCD library to format displayed texts. This enables us to display integers and floating point numbers on the LCD very easily.

Syntax :

sprintf(char * str, const char * format, ...);

Where,

  • str is the pointer to the buffer to which the resulting string is to be stored.
  • format is a constant string or null terminated array of characters. Formatting is done in accordance with this argument.
  • … (additional arguments) indicate a list of additional arguments that may required for this function depending up on the format string. Each additional argument contains a value that to be replace a format specifier in the format string.

Format Specifiers

The generic form of format is %nt. where n is optional which may be 1 – 9 to specify number of characters to be outputted or 01 – 09 to indicate leading zeros or 1.1 to 9.9 for floating point and %w formats. t is the type which may be one of the following.

tType
cCharacter
sSting or Character
uUnsigned Integer
dSigned Integer
LuLong Unsigned Integer
LdLong Signed Integer
xHex Integer – lower case
XHex Integer – upper case
LxHex Long Integer – lower case
LXHex Long Integer – upper case
fFloat with truncated decimal
gFloat with rounded decimal
eFloat in exponential format
wUnsigned Integer with decimal place inserted. Specify two numbers for n. The first is a total field width. The second is the desired number of decimal places.

 Example :

....
float f = 1.414;
int a = 56;
char s[20];
....
....
sprintf(s, "Float = %f", f);
Lcd_Set_Cursor(1,1);
Lcd_Write_String(s);
sprintf(s, "Integer = %d", a);
Lcd_Set_Cursor(2,1);
Lcd_Write_String(s);

This code will make following output on the LCD.

Display Integer and Floating Point Number on LCD

Display Integer and Floating Point Number on LCD

Please go to this page for more details about formatting.

Download Here

If you have and doubts, just comment below. You can download the entire project files here…

Want to See the Output ?


 

Share this post

Comments (130)

  • curiousgeorge

    Hi, I am using PIC16F883 on PICDEM 2 demo board. I have used your code but changed the pin outs to suit the pic16f and demo board. I am curious if using 20mhz external oscillator is timings will need to be adjusted in the code provided

    October 20, 2014 at 11:22 am
  • gabriel

    hey, i’ve donwloaded your code, but it is not compile! build error. can you help me?

    October 20, 2014 at 11:09 pm
  • Ligo George

    Are you sure that you are using MPLAB XC8 compiler.. ??

    Make sure that your compiler is working fine…
    Above projects files are tested and it is 100% working.

    October 22, 2014 at 9:14 am
  • Roy

    I Just completed this project and it works fine. I would like to use a 20×4 display in this project. Do you have a routine that adapts your code to a 20×4 LCD?

    October 26, 2014 at 12:12 am
  • Ligo George

    Thanks for the feedback….
    I am not sure about 20×4 LCD, just try using above library… it might work if the LCD controller is compatible..

    October 26, 2014 at 10:08 am
  • Roy

    Thanks Ligo for your prompt reply. The 20X4 is actually two 40×2 that must be manipulated so that the First, second, third, and fourth line wrap and write correctly. It will require additional coding that is beyond my capabilities at this time. Have a look at the specs on a J204A LCD.

    October 27, 2014 at 12:57 am
  • Ligo George

    It is a clone of HD44780, so the above library will work… You may need to make little modifications in the library, to display in correct positions..

    October 27, 2014 at 6:33 pm
  • Roy

    Yes Ligo, that is the problem, the positions specified within the library. I am afraid that at this point in time my skills in writing code are not up to the task. Could you provide some suggestions or ideas. Thank You.

    October 27, 2014 at 8:42 pm
  • Ligo George

    Check and edit the function for setting cursor position in the header file..

    October 28, 2014 at 8:38 pm
  • Eduardo

    Hello Dear Ligo,

    This library is flexible . this is great feature . I have been looking for it long time.

    First of all , this library is working perfectly on 16×2

    But unfortunately this library isn’t working on 20×4

    Please help me.

    November 16, 2014 at 7:42 pm
  • Ligo George

    If your LCD controller is compatible with HD44780U, that LCD will work… but you may face some issue with display locations..

    November 17, 2014 at 11:56 am
  • Marshall

    I can’t get the file lcd.h I can’t extract it. Can you help me?

    November 18, 2014 at 6:20 pm
  • Marshall

    Or should I say where do I get the file lcd.h ?

    November 18, 2014 at 6:21 pm
  • Ligo George

    Download above zip file and.. unzip it..

    November 18, 2014 at 8:09 pm
  • Ligo George

    Which operating system you are using ?
    In windows, just right click and extract it..

    November 18, 2014 at 8:10 pm
  • Sandro Sarchimelidze

    Thank you for your code. But I get compile error because of delays in lcd.h file. I included but they are only for C18 compiler. What should I do? I’m new in programming so how you can use __delay_ms() without include file? Thanks in advance

    November 19, 2014 at 12:56 am
  • Ligo George

    Hello, the above library is for XC8 compiler.. not for XC18.. they are different..

    November 21, 2014 at 10:11 am
  • shez

    hi, thank you for this, it is very usefull and it works great, can you tell me how I can display a integer. thank you

    January 3, 2015 at 9:37 pm
  • Ligo George January 10, 2015 at 9:02 am
  • Henrique

    Thank you so much for sharing this.

    I am a beginner.

    How can i print variables with this library?

    And in my Mplab works but with 359 error:

    “ADCwithLCDmain.c:267: warning: (359) illegal conversion between pointer types

    pointer to const unsigned char -> pointer to unsigned char”.

    Thanks one mor time!

    January 21, 2015 at 6:31 pm
  • Ligo George

    It is a warning … not error..
    for pring integer and floating point variables you can use sprintf() function.

    January 25, 2015 at 11:58 am
  • krishna

    i need program to controlling a toy car motor , by using mircocontraller ….so what gained of softward i can you’s

    January 30, 2015 at 4:58 pm
  • Ligo George

    Sorry, I don’t understand your question.
    Please use our forums, https://electrosome.com/forums for asking doubts not reated to above article.

    February 9, 2015 at 8:25 pm
  • Edson Archela

    Hi, I test the program but it appears only blank squares on the bottom line. The changes I made are minor: the crystal, to 20MHz; and the port to B. What could be wrong?

    March 2, 2015 at 3:06 am
  • m123

    Excellent work! Routines work great.

    My knowledge of C is lacking and I don’t understand the following results.

    I guess I dont understand what you are testing in the variable ‘a’

    Line taken from Lcd_Init………

    Lcd_Port(0x0C)

    void Lcd_Port(char a)
    {
    if(a & 1) <—- evaluates FALSE in simulator
    D4 = 1;
    else
    D4 = 0;

    if(a & 2) <—— evaluates FALSE in simulator
    D5 = 1;
    else
    D5 = 0;

    if(a & 4) <——- evaluates TRUE in simulator
    D6 = 1;
    else
    D6 = 0;

    if(a & 8) <—— evaluates TRUE in simulator
    D7 = 1;
    else
    D7 = 0;
    }

    March 2, 2015 at 4:47 am
  • Ligo George

    Don’t forget to make that changes in program too.
    Make sure that the connections are correct and the PIC program is running fine..
    Try adjusting the contrast adjusting preset.

    March 2, 2015 at 5:59 pm
  • Ligo George

    It is just to send lcd data to corresponding defined pins…
    It just ANDing “a” and “value”….
    Try to understand it .. just after converting both “a” and “value” to binary.

    March 2, 2015 at 6:01 pm
  • m123

    Thank you for your reply. The key word for me in your response is BOTH.
    Now I see how this routine is just testing to see which bits are set in ‘a’ and sets the corresponding ones for the LCD!

    March 2, 2015 at 6:31 pm
  • Edson Archela

    It was the pic, some burned port. Changed for a new one and work perfectly. Thanks

    March 3, 2015 at 6:23 am
  • khalil louhichi

    HI ,all Can someone help me for programing this circuit with MPLAB XC8 ,on use the pic18f2550 , thanks

    March 13, 2015 at 5:14 pm
  • Piyush Ramani

    lcd.h code where?

    March 13, 2015 at 5:32 pm
  • Piyush Ramani

    Please provide lcd.h header file code

    March 13, 2015 at 5:33 pm
  • Khalil Louhichi

    HI all ,Can someone help me for programing this circuit with MPLAB XC8 ,on use the pic18f2550 , thanks

    March 13, 2015 at 6:25 pm
  • Rahul Carnalious Snal

    Thanks !!!! It’s a great help !!! 🙂 (Y)

    March 15, 2015 at 11:46 pm
  • Rahul Carnalious Snal

    replace the following portion of code in lcd.h and save. then build.

    problem will be solved…….

    void Lcd_Write_String(const char *a)
    {
    int i;
    for(i=0;a[i]!=”;i++)
    Lcd_Write_Char(a[i]);
    }

    March 15, 2015 at 11:48 pm
  • Ligo George

    Please use our forums (https://electrosome.com/forums) for posting doubts not related to above topic.

    March 17, 2015 at 4:59 pm
  • Ligo George

    You can download it above.

    March 17, 2015 at 4:59 pm
  • Piyush Ramani

    Thank you sir…

    March 23, 2015 at 9:23 am
  • Pawel Cuper

    This entire code stops working as soon as I change the properties to Pic18F4520.
    Why?

    April 10, 2015 at 8:57 am
  • Ligo George

    What properties. ?

    April 13, 2015 at 10:35 am
  • shez

    hi, please can you tell me how to make this library work with the PIC18f4520, Nothing happens at the moment I have managed to fix the errors.
    Thanks

    April 24, 2015 at 9:07 pm
  • Ligo George

    Deprecated warning can be solved by using like PORTDbits.RD3
    and for using 8×2 LCD you might need to modify Set Cursor functions.. by changing address values.

    April 27, 2015 at 9:53 pm
  • Piyush

    any one can explain set cursor portion how to select temp value 0x80 and 0xc0 for 2 nd line.

    May 6, 2015 at 4:42 pm
  • Ligo George

    Check the datasheet of the controller HD44780, you can see it.

    May 22, 2015 at 11:56 am
  • watchaphong

    Dear Ligo George

    After build project i found error “can’t open include file “lcd.h”: No such file or directory”.why my compiler don’t have libraly file “lcd.h”. How can i get it from?

    Thank you

    June 6, 2015 at 12:33 pm
  • Ligo George

    Please read the tutorial carefully. You should download the header file “lcd.h”

    June 6, 2015 at 3:58 pm
  • Watchapong HipHip

    OK, i got it. thank you for your tutorial.

    June 6, 2015 at 8:02 pm
  • Mart1n

    Hi, when im trying to use the formatting code for the LCD im getting the error “function declared implicit int” in the lines ” sprintf(a, “Float = %f”, f);” and ” sprintf(a, “Integer = %d”, s);”

    Also, this would work with a 18F45J50?

    Thanks a lot Ligo George

    June 24, 2015 at 1:11 pm
  • Mart1n

    #define _XTAL_FREQ 8000000

    #define RS RD2

    #define EN RD3

    #define D4 RD4

    #define D5 RD5

    #define D6 RD6

    #define D7 RD7

    #include

    #include “lcd.h”

    int main()

    {

    TRISD = 0x00;

    Lcd_Init();

    while(1)

    {

    Lcd_Clear();

    float f = 1.414;

    int s = 56;

    char a[20];

    sprintf(a, “Float = %f”, f);

    Lcd_Set_Cursor(1,1);

    Lcd_Write_String(a);

    sprintf(a, “Integer = %d”, s);

    Lcd_Set_Cursor(2,1);

    Lcd_Write_String(a);

    }}

    June 24, 2015 at 1:12 pm
  • Mart1n

    Would the LCD formatting work with 18F45J50? Thanks a lot Ligo

    June 24, 2015 at 1:16 pm
  • Ammar Yasir

    from where it can be downloaded Ligo ???

    June 30, 2015 at 11:05 pm
  • Ligo George

    It should work. Better to change all port registers to LAT register in all output operations.

    July 1, 2015 at 7:26 pm
  • Ligo George

    Don’t you see the download link above ?

    July 1, 2015 at 7:32 pm
  • Alex Chiang

    Hey I am using PIC16F887. When I use your code, I change all PORTD to PORTA for the data lines (D7~D4) and PORTB (EN, RW,RS) for the command lines. However it does not work. Can you help me with it?

    Below is a picture of what I get on the LCD screen.

    July 29, 2015 at 7:31 am
  • Mauricio Ocón

    did you changed the TRIS and clock configurations? I used the same micro (with PORTD) and worked fine. This is my config

    // CONFIG1
    #pragma config FOSC = INTRC_NOCLKOUT
    #pragma config WDTE = OFF
    #pragma config PWRTE = OFF
    #pragma config MCLRE = ON
    #pragma config CP = OFF
    #pragma config CPD = OFF
    #pragma config BOREN = ON
    #pragma config IESO = OFF
    #pragma config FCMEN = OFF
    #pragma config LVP = OFF

    // CONFIG2
    #pragma config BOR4V = BOR40V
    #pragma config WRT = OFF

    July 30, 2015 at 5:03 pm
  • GB Ward

    Was also able to get this working well with a PIC16F684. Thanks for the library Electrosome! This makes things really easy!

    Specs:
    PIC16F684
    Display connected to PORTC
    No external crystal, using internal oscillator at 4Mhz.

    Notes:
    Initially didn’t work for me, I believe I was having some problems because ADCON0 and CMCON0 weren’t setup for my PIC. No changes to LCD.h necessary at all. sprintf(); will not work on this microprocessor because it requires too much space. See my second post for how to use atoi(); instead to convert integers to char.

    IMPORTANT CODE CHANGES FOR MY SETUP:
    #define _XTAL_FREQ 4000000

    #define RS RC5
    #define EN RC4
    #define D4 RC0
    #define D5 RC1
    #define D6 RC2
    #define D7 RC3


    //Replace CONFIG with
    #pragma config FOSC = INTOSCIO
    #pragma config WDTE = OFF
    #pragma config PWRTE = OFF
    #pragma config MCLRE = OFF
    #pragma config CP = OFF
    #pragma config CPD = OFF
    #pragma config BOREN = OFF
    #pragma config IESO = OFF
    #pragma config FCMEN = OFF

    //PORTS SETUP
    TRISC = 0x00; //PORTC outputs
    TRISA = 0; //PORTA unused
    PORTC = 0; //PORTC intially low
    PORTA = 0; //PORTA initally low
    CMCON0=7; //Comparators off, and all pins I/O
    ANSEL=0; //Select no A/D
    ADCON0=0; //ADC off.

    Hopes this helps or inspires somebody.

    August 6, 2015 at 8:28 am
  • GB Ward

    CONVERTING AN INT WITH ATOI

    If your processor won’t handle sprintf(); or it’s using up too much space, and you just only need to print an int, try the atoi(); function. It’s available in the XC8 Complier library, see page 369.

    Requires:
    #include

    Sample Code:

    int j = 14; //declare int and put 14 in it.

    char buffer[17]; //Allow 16char + one null for 16 character display
    itoa(buffer, j, 10); //convert int j to ASCII, base 10. Load into char buffer[];
    Lcd_Set_Cursor(2,1);
    Lcd_Write_String(buffer);

    This code will write the number value of j, in this case 14, on the display on the second line. Helpful if you are building a simple counter or wanting to print the result of some int manipulation.

    August 6, 2015 at 8:36 am
  • Luca

    I can not find the lcd.h file. it has been removed?

    August 6, 2015 at 12:01 pm
  • Ligo George

    PORTA is the analog port. Set all pins to Digital by writing to appropriate registers. Also disable other functions like comparator.

    August 14, 2015 at 9:25 pm
  • Ligo George

    Dear GB Ward,
    Thanks for the feedback.

    August 14, 2015 at 9:36 pm
  • Ligo George

    No, you can download it above. It is the zipped project folder.

    August 14, 2015 at 9:39 pm
  • Efrain Torres

    Hi,
    I would like to use a less costly micro such as PIC16F57 with a 16X2 LCD. Is this code work for the mentioned micro or what considerations I should take?

    August 20, 2015 at 3:30 am
  • Ligo George

    Yes, you can use the above header file for that.

    October 3, 2015 at 1:02 pm
  • Mahesh Fernando

    Hi, Your code work perfect. I am trying to understand the code. Not clear how following statements work. 1) temp = 0x80 + b – 1; 2) temp = 0xC0 + b – 1; 3) for(i=0;a[i]!=”;i++). Please explain. Thanks.

    October 17, 2015 at 7:06 pm
  • Mike

    How can I create or make a custom character an print it into the LCD??

    October 24, 2015 at 10:36 am
  • Mike

    How can I create or make a custom character and print it into the LCD?

    October 24, 2015 at 10:38 am
  • Kevin Ponce

    Hi, I´m trying this code in Mplab, but when i generate the .hex I can´t run it in PIC Simulator it shows me this message: “Invalid program file in Hex Format contains error. Line number 197: Invalid data byte in the record. ” Can You tell me why?

    November 13, 2015 at 12:00 pm
  • Ligo George

    You have to read the LCD Controller datasheet (HD44870) for that.

    November 21, 2015 at 1:21 pm
  • Ligo George November 21, 2015 at 1:49 pm
  • Ligo George

    Above code is 100% working. I don’t know PIC Simulator. You can try using Proteus.

    November 23, 2015 at 7:23 am
  • ahmed ammar

    Ligo George ,

    how are you? i am looking for a a circuit diagram which consist of pic18F4520 and the sensor, the target of this circuit that I need when it is below 6 meters the sensor give a signal to the pic to make yellow led is flashing, while when the sensor reach exactly to 6 meters the pic give a signal to switch off yellow led and make green led is on, if the sensor exceed 6 meters the red led is on and giving sound to the buzzer.
    if you do not mind could you help me in that please with the code using Proteus program.
    Regads,
    Ahmed

    November 28, 2015 at 12:41 am
  • ahmed ammar

    Ligo George ,

    how are you? i am looking for a a circuit diagram which consist of pic18F4520 and the sensor, the target of this circuit that I need when it is below 6 meters the sensor give a signal to the pic to make yellow led is flashing, while when the sensor reach exactly to 6 meters the pic give a signal to switch off yellow led and make green led is on, if the sensor exceed 6 meters the red led is on and giving sound to the buzzer.
    if you do not mind could you help me in that please with the code using Proteus program.
    Regads,
    Ahmed

    November 28, 2015 at 1:15 am
  • Electo

    Hi,

    thanks for your code.
    I use it on picdem2plus demoboard with a Pic18F452 and XC8 and it works (after pin modifications).
    But I have warnings for each time I call Lcd_Write_String() function, here is the warning:
    “Warning [359] illegal conversion between pointer types
    pointer to const unsigned char -> pointer to unsigned char”
    Now on my program I call 34 times this function, but I use it one more time the programmin delay is long and after powering the board nothing on the LCD.
    Any one can help?

    December 1, 2015 at 3:10 pm
  • Omoniyi Omotoso

    Hi, thanks for this great tutorial, please how can i correctly
    set cursor, shift left and right on a 20×4 LCD display with this same
    library. I have tried it but it is not working as it should. Thanks in advance

    December 17, 2015 at 9:58 pm
  • Ligo George

    Sorry, your question is outside the scope of above article. Please use our forums ( https://electrosome.com/forums ) for such questions.

    December 19, 2015 at 3:20 pm
  • Ligo George

    Warning is not a problem. If you want to remove it, just add const prefix to each string argument in the function definition.

    It seems like you have used more than 70% of the PIC ram by using strings, it might be the problem. Reduce strings or replace PIC with a higher one.

    December 19, 2015 at 3:39 pm
  • Ligo George

    Check your LCD datasheet. You might need to make minor changes in the address in library.

    December 19, 2015 at 3:59 pm
  • prathap gangadhar

    hello sir, how to give password to lock and unlocking in LCD display, please send me the code sir

    February 8, 2016 at 3:57 pm
  • Legit

    Hi Ligo,
    Could you please send me the link to download the MPLab XC8 Compiler to execute the above program? I’m not able to find a reliable link.
    Thanks in advance. 🙂

    February 10, 2016 at 12:36 pm
  • akmal 94

    #include

    how to get this file header pls help

    February 21, 2016 at 8:49 pm
  • akmal 94

    picc.exe –pass1 –errformat=”Error at file %%f line %%l column %%c: (%%n) %%s” –warnformat=”Warning at file %%f line %%l column %%c: (%%n) %%s” –msgformat=”Message at file %%f line %%l column %%c: (%%n) %%s” -D_XTAL_FREQ=1000000 -G –chip=16F877A -O”main.p1″ “../main.c”

    HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode) V9.82

    Copyright (C) 2011 Microchip Technology Inc.

    (1273) Omniscient Code Generation not available in Lite mode (warning)

    Warning at file ../main.c line 11 column 26: (111) redefining preprocessor macro “_XTAL_FREQ” ((null): 0)

    Error at file ../main.c line 20 column 15: (141) can’t open include file “xc.h”: No such file or directory

    make: *** [main.p1] Error 1

    Error code 2

    February 21, 2016 at 8:52 pm
  • akmal 94

    need help pls

    February 21, 2016 at 8:53 pm
  • Ligo George

    It is there by default for XC8 compiler.

    February 27, 2016 at 8:00 pm
  • Ligo George

    Above code is for XC8 compiler .. not for Hi-Tech C… Just change the header file xc.h to htc.h.

    February 27, 2016 at 8:02 pm
  • b0rg

    hi, Im trying to compile your code with MPLAB XC8, but I’m having problems with delay functions. I use the same crystal together with pf184550 but for some reason when i compile it says that the “in-line delay argument too large”, when i lover it from 2000 to 90 it passes that error. Why is that happening. Thanks

    April 8, 2016 at 5:34 pm
  • Ligo George

    That is due to delay limit. You need to make another used defined function, something like this :

    void Delay10(unsigned a)
    {
    for(;a>0;a–)
    {
    __delay_ms(10)
    }
    }

    April 15, 2016 at 8:16 am
  • sampath

    thank you very much GB ward it worked

    April 27, 2016 at 1:20 pm
  • Boris

    Thanks bro you literally saved me days of hacking, tacking and patching to get my own working code.

    May 30, 2016 at 9:58 pm
  • Ligo George

    Thanks for the feedback.

    June 2, 2016 at 6:18 pm
  • Ghislain

    Hello, I’m trying since 3 week to display a 2×16 LCD but it is not working. I use the PIC16F1937 MCU. can you please help me? please!!!

    June 28, 2016 at 9:43 pm
  • Ali Alaa

    Thanks alot man, your code is neat, straight forward and flawless; it was very helpful

    June 29, 2016 at 5:37 am
  • Ligo George

    Please give the details of the problem you are facing. What is the current output ? Put photos and code here.

    August 27, 2016 at 12:55 pm
  • Ligo George

    Thanks for the feedback.

    August 27, 2016 at 12:56 pm
  • Jaguar paw

    Please please please!! can some one help I cannot get it to work.
    I only get the top row showing blocks as if I am only applying power.
    I am using the pic16f690.

    I have made the following changes and connections

    #define RS RC0
    #define EN RC1
    #define D4 RC2
    #define D5 RC3
    #define D6 RC4
    #define D7 RC5

    also I have TRISC 0x00

    I am using the internal clock and as far as I know I have emended the code accordingly

    lcd.h

    #include
    //LCD Header for 4 bit Data -MPLABX/XC8
    #define _XTAL_FREQ 8000000
    #define RS RC0
    #define EN RC1
    #define D4 RC2
    #define D5 RC3
    #define D6 RC4
    #define D7 RC5
    char temp,z,y;
    int i;
    void Lcd_Port(char a)
    {
    if(a & 1)
    D4 = 1;
    else
    D4 = 0;

    if(a & 2)
    D5 = 1;
    else
    D5 = 0;

    if(a & 4)
    D6 = 1;
    else
    D6 = 0;

    if(a & 8)
    D7 = 1;
    else
    D7 = 0;
    }
    void Lcd_Cmd(char a)
    {
    RS = 0; // D0 to D7 interpreted as Command

    Lcd_Port(a);
    EN = 1; // LCD Enable
    __delay_ms(4);
    EN = 0; // LCD Disable
    }

    Lcd_Clear()
    {
    Lcd_Cmd(0);
    Lcd_Cmd(1);
    }

    void Lcd_Set_Cursor(char a, char b)
    {
    char temp,z,y;
    if(a == 1)
    {
    temp = 0x80 + b – 1;
    z = temp>>4;
    y = temp & 0x0F;
    Lcd_Cmd(z);
    Lcd_Cmd(y);
    }
    else if(a == 2)
    {
    temp = 0xC0 + b – 1;
    z = temp>>4;
    y = temp & 0x0F;
    Lcd_Cmd(z);
    Lcd_Cmd(y);
    }
    }

    void Lcd_Init()
    {
    Lcd_Port(0x00);
    __delay_ms(20);
    Lcd_Cmd(0x03);
    __delay_ms(5);
    Lcd_Cmd(0x03);
    __delay_ms(11);
    Lcd_Cmd(0x03);

    Lcd_Cmd(0x02);
    Lcd_Cmd(0x02);
    Lcd_Cmd(0x08);
    Lcd_Cmd(0x00);
    Lcd_Cmd(0x0C);
    Lcd_Cmd(0x00);
    Lcd_Cmd(0x06);
    }

    void Lcd_Write_Char(char a)
    {
    char temp,y;
    temp = a&0x0F;
    y = a&0xF0;
    RS = 1; // D to D7 interpreted as DATA
    Lcd_Port(y>>4); //Data transfer
    EN = 1;
    __delay_us(40);
    EN = 0;
    Lcd_Port(temp);
    EN = 1;
    __delay_us(40);
    EN = 0;
    }

    void Lcd_Write_String(char *a)
    {
    int i;
    for(i=0;a[i]!=”;i++)
    Lcd_Write_Char(a[i]);
    }

    void Lcd_Shift_Right()
    {
    Lcd_Cmd(0x01);
    Lcd_Cmd(0x0C);
    }

    void Lcd_Shift_Left()
    {
    Lcd_Cmd(0x01);
    Lcd_Cmd(0x08);
    }

    main.c
    #define _XTAL_FREQ 8000000

    #define RS RC0
    #define EN RC1
    #define D4 RC2
    #define D5 RC3
    #define D6 RC4
    #define D7 RC5
    // BEGIN CONFIG

    #pragma config FOSC = INTRCCLK // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = ON // MCLR Pin Function Select bit (MCLR pin function is MCLR)
    #pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
    #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
    #pragma config BOREN = ON // Brown-out Reset Selection bits (BOR enabled)
    #pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)
    #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

    //END CONFIG
    #include

    #include “lcd.h”;

    void main()
    {
    unsigned int a;
    TRISC0 = 0x00;
    TRISC1 = 0x00;
    TRISC2 = 0x00;
    TRISC3 = 0x00;
    TRISC4 = 0x00;
    TRISC5 = 0x00;
    Lcd_Init();
    while(1)
    {
    Lcd_Clear();
    Lcd_Set_Cursor(1,1);
    Lcd_Write_String(“LCD Library fr”);
    __delay_ms(290);
    //Lcd_Set_Cursor(2,1);
    //Lcd_Write_String(“MPLAB XC8”);
    //__delay_ms(100);
    //Lcd_Clear();
    //Lcd_Set_Cursor(1,1);
    //Lcd_Write_String(“WWW.ALSELECTRO.COM”);
    //__delay_ms(100);
    //Lcd_Clear();
    //Lcd_Set_Cursor(1,1);
    //Lcd_Write_String(“Saravana Electronics”);
    }
    /* for(a=0;a<15;a++)
    {
    __delay_ms(10);
    Lcd_Shift_Left();
    }

    for(a=0;a<15;a++)
    {
    __delay_ms(10);
    Lcd_Shift_Right();
    }

    Lcd_Clear();
    Lcd_Set_Cursor(2,1);
    Lcd_Write_Char('S');
    Lcd_Write_Char('E');
    __delay_ms(10);
    }
    */
    }

    September 8, 2016 at 9:44 pm
  • mash

    Hi
    How may I run two hour meter with same speed.?
    I tried but I am getting 1 sec delay in each increments.
    Hour1-0000
    Hour2-0001
    while I want
    Hour1-0000
    Hour2-0000

    Hence I want that both hourmeter should run with incremental rate.

    September 8, 2016 at 11:45 pm
  • Ligo George

    Hi,
    Make sure that all connections are correct and also try adjusting the contrast.

    September 10, 2016 at 10:32 pm
  • Jaguar paw

    Yes i believe they are also would i need to check contrast if backlight is not connected?

    September 11, 2016 at 5:08 am
  • Jaguar paw

    I haave checked the connections and they seem fine. Would i need to worry about contrast if the backlight is not used ? I still have no luck !:(

    September 12, 2016 at 12:00 am
  • Joan

    Hi, I am a rather late entrant to this world. Your LCD program works great! However have problems when using the sprint method to display the examples you shared viz., the Float and Integer. MPLAB X IDE returns “…..error 1098 conflicting declarations for variable “_sprintf”. Also “Build failed”. Your inputs will be of great help. I can share the code sample if required. Thanks

    September 13, 2016 at 1:42 pm
  • Ligo George

    Yes, contrast and backlight are different.

    September 14, 2016 at 12:36 pm
  • Ligo George

    did you include the header file ?? and make sure that your sprintf syntax is correct.

    September 14, 2016 at 12:43 pm
  • Joan

    Hi Ligo, Yes the header file is included and the main program is working great. The problem is only with the ‘sprintf’ example – I copied the code exactly as given but the program is returning ‘ build failed’. There are some empty spaces (dots) in your example, what does this mean. Appreciate your help. Thanks

    September 15, 2016 at 3:29 pm
  • Joan

    Hi, As I can see if you are using Internal Clock you also need to set OSCCON in your main program e.g. OSCCON = 0x071; This will set the internal clock to 8Mhz

    September 15, 2016 at 5:57 pm
  • Ligo George

    You need to include the header file stdio.h for that.

    September 22, 2016 at 7:22 pm
  • Tim

    First, thanks a lot, this tutorial and the one for interfacing the HC-SR04 are awesome!!

    So I am having issues trying to get the code to compile. I am using the dsPIC33f with XC16 compiler to attempt to build this. I have changed all of the RDs to RBs, as my chip doesn’t have port D available. I am running into the issue within the lcd.h file and it is giving me the error that ” ‘RB4’ undeclared (first use in this function)” for pretty much all of the RB pins. Also, within the main.c I am getting errors for all of the pragma config statements “unknown configuration setting: ‘FOSC'” etc. Any help you might be able to give would be much appreciated. Thanks!

    September 30, 2016 at 12:28 am
  • Tedro Chalouhy

    In the proteus circuit, the LCD LM016L does not have the last two ports LED+ and LED-
    i have loaded ur code to the pic16F877A and did all the connections the way u did except for those two LED ports in the lcd, and the lcd didn’t show anything when i ran it, any help?

    October 21, 2016 at 8:40 pm
  • Ligo George

    This code won’t work in dsPIC. You need to make a lot of changes for that.

    November 27, 2016 at 12:59 pm
  • Ligo George

    That is not a problem. For simulating LED is not required. It will work fine in simualtion without those LED connections.

    November 27, 2016 at 1:22 pm
  • Ligo George

    It means that you need to reduce the delay. Just split it in to two delays and try.

    November 27, 2016 at 2:45 pm
  • Ivan

    Hi, I need to show 4 messages in differents lines , I have intented with “LM044L” LCD, but until now I have been unable. Thanks

    November 28, 2016 at 4:21 am
  • Ligo George

    Check the datasheet of your LCD controller, you might need to make some changes depending on it.

    November 28, 2016 at 11:02 am
  • Lijin

    Hi, Ligo can you provide xc8 code for 16×1 LCD interfacing with PIC?? Thanks in advance.

    April 4, 2017 at 12:49 pm
  • kunal

    Hi Ligo, I need your help.. your code is working fine.. I want to add underline cursor or blinking cursor.. can you suggest some way for this? I tired but i am facing some issues.

    April 19, 2017 at 12:42 pm
  • irmkrky

    Programming Target (4/28/2017 12:54:35 PM)
    PIC16F877A found (Rev 0x8)
    Erasing Target
    Programming Configuration Memory
    Verifying Configuration Memory
    PK2Error0027: Failed verify (Address = 0x2007 – Expected Value 0x2F4A – Value Read 0xA85)
    PICkit 2 Ready

    We have encountered this problem when the code is programmed. What can I get rid of this problem?

    April 28, 2017 at 3:33 am
  • Coco

    This code is ok with a PIC16F1619 microcontroller ?

    August 9, 2017 at 2:11 am
  • Edwin Juarez

    HI, Who i can print pixel whit the LCD, creating news caracters, example pacman or gasper

    November 2, 2017 at 1:40 am
  • Sefa ASLAN

    Thanks for the tutorial. I am new to programming pic microcontrollers and I have a problem. I am trying to program a PIC16F877A to run a nokia 5110 display. In the codes you provided, lcd.h library is used. However it seems like I do not have it in my MPLABX v4.05. Do you have link to download the library?

    November 18, 2017 at 7:03 pm
  • hacker kribo

    Yeah great post … Can i get the code for LCD interface ? thanks in advance (mail id – [email protected])

    November 29, 2017 at 10:50 pm
  • Rubén Henríquez

    Thanks

    February 1, 2018 at 9:56 am
  • jayesh

    HI SIR. If i use pic18f248 processor, what modifications need to be done? i am using 16 mhz oscillator with a hardwear device

    February 7, 2018 at 12:47 pm
  • Jack Kosovi

    it misses the file lcd.c so that it works, it is not in the zip fil

    February 10, 2018 at 2:53 am
  • Koppula Jaswanth

    Hey where can i get LCD.h and UART.h files

    March 30, 2018 at 9:34 pm
  • Ligo George

    Link is already provided in the above article.

    April 2, 2018 at 12:36 pm
  • Ligo George

    Did you tried other programs ? It is not an error of above program. Try changing the microcontroller or programmer.

    April 6, 2018 at 3:08 pm
  • sefa melek

    hello . We need some help and ı was hoping you can help us.
    We have one school project about servo motor and we had some research but we couldnt find anything yet. we study electrical-electronic engineer so it is not so easy for us. We used matlab, arduino , labview , autocad. And now it is diffrent program for project. And we are not professional on mplab .

    My project make servo motor with mlabx -xc8 and we will use keypad and LCD. Also we will use PIC16f877a . İt taked so much days and our final week came. So ı losted. I hope you can help us. Thank you . And best regards.

    May 2, 2018 at 3:32 am
  • Sławek Wiśniewski

    I have warning, MPLAB V5 XC8, PIC18F4550, Internal oscillator,
    but it works great, It’s a great help !!!

    warning is

    ./lcd.h:7:3: warning: ‘RD4’ is deprecated [-Wdeprecated-declarations]
    D4 = 1;
    ^
    main.c:5:12: note: expanded from macro ‘D4’
    #define D4 RD4
    ^

    July 25, 2018 at 3:02 am
  • Aditya Adiga

    Thanks . your code works for pic16f877a. I have a problem that i want lcd display output using pic16f1509. I did simulation in proteus using pic16f1509. I got proper lcd display output in simulation but practically i’m getting blinking of boxes in lcd display. Please suggests me , what are the changes have to be done ?

    January 16, 2019 at 12:42 am
  • Fabri

    I need this

    February 27, 2019 at 10:02 am
  • Võ Hoàng Sơn April 2, 2019 at 2:48 pm

Leave a Reply

Your email address will not be published. Required fields are marked *