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. You should include the header file stdio.h for using sprintf().

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.

t Type
c Character
s Sting or Character
u Unsigned Integer
d Signed Integer
Lu Long Unsigned Integer
Ld Long Signed Integer
x Hex Integer – lower case
X Hex Integer – upper case
Lx Hex Long Integer – lower case
LX Hex Long Integer – upper case
f Float with truncated decimal
g Float with rounded decimal
e Float in exponential format
w Unsigned 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

  • You should include the header file stdio.h to use sprintf(). By the way thanks for asking this question, I have included this information in the article also.

  • Hi. I cannot use the sprintf function. I get an error in building the code. How should be included, the sprintf function?

  • I am not sure about this particular LCD. But you can use any LCD which uses a controller compatible with HD44780. So first check whether this LCD controller is HD44780 compatible. If not you might need to make minor changes as per the specifications of that particular controller. In my experience, most of these kinds of LCD’s controller are compatible to HD44780.

  • Hello, Ive ordered the pic you re using, but my lcd is a qapass 16×2 lcd ( from the elegoo mega 2560 kit). From your experience, do you know if the lcd controller is compatible or do i need to buy a new lcd…where did you buy yours from? Does it exist on amazon or ebay? If yes could you provide a link?
    Thank you!!!

  • 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 ?

  • 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
    ^

  • 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.

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

  • 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?

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

  • 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?

  • 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.

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

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

  • 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?

  • 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!

  • 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

  • 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

  • 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

  • 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 !:(

  • 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.

  • 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);
    }
    */
    }

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

  • 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!!!

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

  • 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)
    }
    }

  • 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

  • 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

  • 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. 🙂

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

  • 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.

  • 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

  • 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?

  • 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

  • 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

  • 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?

  • 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.

  • 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?

  • 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.

  • 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.

  • 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

  • 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.

  • #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);

    }}

  • 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

  • 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

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

  • 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.

  • 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

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

  • 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]);
    }

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

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

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

  • 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!

  • 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.

  • 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.

  • 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;
    }

  • 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?

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

  • 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!

  • 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

  • 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

  • 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.

  • 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.

  • 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..

  • 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.

  • 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?

  • 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.

  • 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


  • >