Microchip PIC Library to Control a 20 by 4 LCD Over I2C

Introduction: Microchip PIC Library to Control a 20 by 4 LCD Over I2C

This Instructable presents a 'C' library for controlling a single 20 by 4 LCD based on the HD44780 LCD controller over I2C using the NXP PCF8574 Remote 8bit IO Expander. The LCD is configured for 4 bit interfacing and can be written to and read from via the microcontroller. In this case the PIC18F2685 running at 4MHz.

To use the source and create the microcontroller circuitry you will need to be reasonably au fait with Microchip microcontrollers, the 'C' programming language and electronics in general.

In short, it's not for the beginner. I have included the source code and MPLABX project to get you up and running quickly. It is provided free to use in what ever way you see fit (just make a mention of me), though it comes unsupported.

I used the following system set up;

  1. PIC18F2685 (4MHz XTAL). Purchased from MicrochipDIRECT. £5.30
  2. 20 by 4 2004A LCD based off HD44780. Purchased from Ebay £3.57.
  3. MPLABX IDE v2.15. Free from Microchip
  4. Microchip compiler XC8 v1.35. Free from Microchip
  5. I2C to 1602 convertor board. Purchased from Ebay £1.79
  6. MPLABX XC8 Peripheral Library. Free from Microchip.

I created the library as part of a project to build a bus pirate for my Scantronic 9800 house alarm. Its an old alarm and I want to add internet and GSM connectivity to it without paying the outrageous UK prices. This is part of the first steps to 'crack' the comms between control box and remote key pad.

As I couldn't find a well written library with all the functionality I wanted I decided to 'roll my own.'

Step 1: The Hardware

As mentioned earlier I used the PIC18F2685 primarily due to footprint and space constraints in the finished project.

This meant I was strapped for IO given this is a 28 pin PDIP package. As the peripheral comms was not particularly high speed and I wanted to add an EEPROM and an RTC the logical choice was for I2C as the comms to the LCD. Microchip offer an outstanding free Peripheral Library for the 8bit Microcontrollers which made life a lot easier.

I purchased a vanilla 2004A 20 by 4 LCD from Ebay (£3.57)

and a '1602LCD Display IIC/I2C/I/SPI Serial Interface Module Port For Arduino K6' (£1.79). I have no idea how Ebay sellers decide on these titles.

I soldered the two together and wired them up to the microcontroller as shown in the Pics above.

Step 2: The Software

As mentioned earlier I have included a zipped copy of the full source including the MPLABX project this should allow you to try out the code as quickly as possible (all the include paths are relative).

The software comprises 4 main parts;

  1. The LCD Driver Library : LCD_I2C_PCF8574.c and .h
  2. The I2C bus access code : I2C_UTILS.c and .h
  3. The time delay calls : DELAY.c and .h
  4. The main code : main.c

There are some other files; mcc.c/.h, pin_manager.c/.h. These were added by the Microchip code configurator and I left them in.

I looked at a few libraries (Arduino ones) to get inspiration. In LCD_I2C_PCF8574.c I have added a lot of background and links to where you can get hold of other source, documentation and data on the PIC18F2685, I2C, the LCD and IO expander should you be so inclined. I also added a link to the library I ripped for the character generation. Thanks Mario. This file also contains details on how you may want to customise to your implementation, these are tagged with 'TODO adapt' so you can use the MPLABX task list to grab them.

I took all my details/nomenclature etc. from an Hitachi hard copy LCD manual (yes hard copy, real paper an'all!) I obtained in the early 1980's when we were still printing on flattened trees.

The code in main.c exercises all the functionality of the display including reading DD and CG ram and the busy flag. It should give a good heads up on how to use the library. I included a link to a YouTube Video so you can see it's potential.

Happy experimenting.

Be the First to Share

    Recommendations

    • Micro:bit Contest

      Micro:bit Contest
    • Halloween Contest

      Halloween Contest
    • Home Cooked Speed Challenge

      Home Cooked Speed Challenge

    30 Comments

    0
    JoseG421
    JoseG421

    2 years ago

    Hi Steve!
    I sincerelly want to thank you for sharing your work.
    Your library is working nicely at a PIC32MK1024GPD064.

    im1.jpeg
    0
    RollingRocker
    RollingRocker

    Reply 1 year ago

    Can you please post your working project? Thanks

    0
    JoseG421
    JoseG421

    Reply 1 year ago

    Hi! Sorry for the delayed response, I've just seen it.
    Unfortunately, I don't know how to post my project here. I'm working on a GitHub account to keep all my projects. It should be ready in a couple of days and there you should be able to look at the code. In the meantime, I mostly work on PIC32 devices and I'll be happy to help. What are you struggling with?

    0
    SteveQuinn
    SteveQuinn

    Reply 2 years ago

    You're very welcome Jose, glad it was of some use.

    0
    AntHulett
    AntHulett

    1 year ago

    Hi Steve - great work!
    After a bit of struggling I got it working with a PIC18F14K22 using the MCC-generated I2C calls. The main issue was that MCC assumed a register was needed for every I2C device, but of course the PCF8574 doesn't have any. In the end I just passed the data in the 'reg' parameter as well as the 'data', and it worked. I imagine I'm sending everything down the line twice (which might cause problems with some calls) but it's good enough for now.

    0
    RollingRocker
    RollingRocker

    Reply 1 year ago

    @AntHulett can you please post a ZIP of your project here? I am having a lot of issues getting this running under MPLAB 5.40 and XC2.20. Thank you

    0
    AntHulett
    AntHulett

    Reply 1 year ago

    Hi,
    First of all check whether your display has a PCF8574 or an MCP23017 expander.
    Steve's project has code for both, but I've only tried PCF8574.
    I used MCC to specify internal oscillator 1MHz and used the MSSP Peripherals to specify that it's an I2C Master.
    I didn't use lcd_utils, as that seems to be for the MCP23017.
    I didn't use timer_files, just changed every DelayMicroseconds() to __delay_us().
    I didn't use the i2c_utils, but went straight to the MCC-generated examples.
    And I didn't left-shift the PCF8574 address, but used it as-is (which seems to contradict the documentation, but it works...).
    So you end up with 3 source files, which I've attached here (Instructables only seems to allows image uploads, so you'll need to remove the '.jpg' from the file name to get the actual zip file!).
    Good luck!

    LCD_MCC_Mods.zip.jpg
    0
    RollingRocker
    RollingRocker

    Reply 1 year ago

    Ant-
    THANK YOU so much. Will work on testing this today. My setup is exactly the same as the Author's and yours and uses the PCF8574T on a cheap 4x20 that I got off ebay.
    I did a quick review of your code. I don't seem to see any direct hardware MSSP port references; my PIC18F6722 has two MSSP interfaces on it. Do I need to specify which one is being used, and if so how do I do this?
    Thank you again!

    0
    AntHulett
    AntHulett

    Reply 1 year ago

    @RollingRocker, I just used the MCC graphical interface to specify that I wanted to enable MSSP as I2C Master. If your chip has 2 MSSP interfaces, I would imagine that the GUI would reflect this and allow you select which one you want to use. It generates all the hardware-level code for you, so you can use the high-level I2C_Read_/I2CWrite_ functions.

    0
    SteveQuinn
    SteveQuinn

    Reply 1 year ago

    Thanks Ant,
    I wrote this quite some time ago now. I seem to remember I used the MPLABX XC8 Peripheral Library as it did all the Donkey Work at the register level. I totally forgot I did two versions one for the MCP23017 (8 bit interface) and PCF8574 (4 bit interface). Both variants use the I2C_UTILS.h file. It just ensures the correct I2C sequence appears on a given interface, which I checked with my scope.
    At the time the 8 bit seemed such a waste and I had just figured out what the PCF8574 I/O board was used for (strap it to the back of an LCD interface) so I wrote the PCF driver. I then ported this to an Arduino library which I've been using ever since.
    I went on to create another Instructable with the equivalent Arduino library version, here;
    https://www.instructables.com/id/Arduino-I2C-LCD-Driver-Library-and-PackMan/
    It has a lot of information which may explain the 'left shifting thing', there's also an excel spread sheet which can be used to generate characters for the display.
    Best Regards
    SteveQ

    0
    JohnArduPic
    JohnArduPic

    2 years ago

    Thank you Steve !
    I just got it working with dsPIC30F4011. (lots of learning on my part, and some changes required. - I used the TaurTech I2C library I found on GitHub that was reference by an article on I2C control using dsPic30F family - minor changes to that due to PCF8574 NOT having registers. Also changed all the delays to the _ _ delay_uS() and _ _ delay_mS() style supported by stock Microchip libraries). dsPIC configured to run internal clock 30 MHz. Used XC16 v1.41, MPLAB-X 5.25

    0
    RollingRocker
    RollingRocker

    Reply 1 year ago

    Can you post your working project via a ZIP for all of us to see?
    Thanks

    0
    SteveQuinn
    SteveQuinn

    Reply 2 years ago

    Hey John,
    Outstanding crossporting! I'm glad you found it useful.
    Best Regards
    Steve

    0
    RollingRocker
    RollingRocker

    1 year ago

    I am struggling to get this working under MPLAB 5.40 (current version) and XC8 2.20 (also current). Lots of issues to resolve but working through them. It is mandatory to download and install the peripheral libraries and then add the paths inside the complier preferences.
    Still unable to fully compile it without a few errors and warnings.
    Would really appreciate if you could update this to work under the most current MPLAB.
    Also it would be good if we could get a very streamlined version of this (which I am willing to work on), providing I can get this to compile and work.

    0
    SamV63
    SamV63

    1 year ago

    First: Congrats man, this is an unit of accomplishment!
    Second: Have anyone ported this to MikroC and PIC18F4550?

    0
    aivaras.svageris
    aivaras.svageris

    3 years ago

    Hi Steve!
    Can i configurate this code for PIC18F26k22?
    Is it even possible?
    I would use it on 16 by 2 LCD based on the HD44780 LCD controller over I2C using the NXP PCF8574 Remote 8bit IO Expander, it would have to work?

    0
    AkeemS2
    AkeemS2

    Reply 2 years ago

    Please I try port the code and use it on pic18f25k83 but it isn't working...can u guide me on how you were able to port the code?.. thanks

    0
    SteveQuinn
    SteveQuinn

    Reply 3 years ago

    Hi aivaras

    It's been a while since I did any PIC work. Its an 18F as was the device I used so the MPLABX XC8 Peripheral Library should be ok. You may need to play around with the row and columns though.

    Regards

    SteveQuinn

    0
    SteffenD3
    SteffenD3

    2 years ago

    Sorry, its can never running! The PIC18F2685 never found in MCC. I tested from Version 2.25.2 to 3.66 now. PIC18F26K22 found, but PIC18F2685 generated a Error in MPLABX. And i missing the file *.mc3 in project and so on...

    LCDDriver1.JPG
    0
    SteffenD3
    SteffenD3

    Reply 2 years ago

    And my Compiler is never running okay. I always get exotic mistakes.

    LCDDriver_Error_XC8.JPG