Proton BASIC Compiler - I2C LCD

  • PicŪ Basic

  • I2C LCD

    In the course of several projects, I have found having an LCD for status output during de-bugging, as well as operation, is a significant advantage. However, every time I used an LCD in a project it consumed six of the PICŪ I/O pins. Since all of my PICŪ projects thus far have used 18DIP devices, six I/O pins is a substantial resource cost.

    Recently, I did a real time clock using an i2c RTC device, (DS1337). I got to thinking that if I had an LCD display that was i2c I could not only reduce the number of I/O pins needed, but also move to a more 'modular' approach in my projects. The modular approach would also provide me with 'ready made' chunks that I could just hang on the i2c buss as needed. For instance a data logger could now have RTC info for the logging output with the addition of an i2c RTC. I could expand the memory available for data or event capture. You get the idea. Assemble the building blocks and use them as needed, where needed.

    I happen to have an unused two line LCD display based on the industry standard Hitachi 44780 controller. Proton makes using an LCD a snap The same for using i2c devices. Now how to combine them?

    I started by building an LCD/PICŪ module using a 16F819. The 16F819 has a Synchronous Serial Port, (SSP) with onboard i2c support and 2kb of program memory. I first built the PICŪ on a PICŪ proto board I had on hand. I wired the LCD to it and tested printing to the LCD with a 'Hello World' type program. I used the connection information found in the Proton manual pages for the "Print" command. Once the LCD was known to be working, the next task was to get the PICŪ to receive i2c data and print it to the LCD. I found the "i2c_Slave.bas" program supplied by Crownhill in the samples folder of Proton Development Suite. The i2c_Slave program is a basic skeleton framework for sending and receiving data over the i2c buss.

    By adding the appropriate declares for LCD and i2c operation and inserting a small print routine I was in business.

    If buff != 0 Then ;Print byte to LCD Print buff buff = 0 ;Clear Buff EndIf

    The i2c LCD display works well, however, I did find that after some control commands, ($FE,1 etc), a small (5ms) delay was needed before I sent the next byte to the display. Currently I add this delay in the program that uses the display. I will probably move this to the i2cLCD program in a future version.

    This is not intended to be a comprehensive 'how-to', but I hope I have provided enough information for you to be well on your way.

    ;File Name: i2cLCD101.bas
    ;Version: 1.0.1
    ;ProtonPlus DS: v3.1.5
    ;Program to read data and format command and print to LCD
    ;via i2c buss. This program is derived from i2c_Slave.bas
    ;supplied by Crownhill with Proton Development Suite.
    ;Release History
    ;v001 Initial prerelease - Tests LCD printing from PICŪ board
    ;v002 First attempt LCD i2c slave operation
    ;v003 Basic functions working OK. Unit receives a byte from
    ; the i2c bus and prints it to the LCD
    ;v004 Added device address to banner
    ;v100 First 'working' release
    ;v101 Removed un-needed SSPCON2
    ; Revised comments regarding TX & RX
    ; Port A MAP
    ; Bit Pin Function
    ; A.0 17 (out) LCD DB4
    ; A.1 18 (out) LCD DB5
    ; A.2 01 (out) LCD DB6
    ; A.3 02 (out) LCD DB7
    ; A.4 03 (N/A) Not used
    ; Port B MAP
    ; Bit Pin Function
    ; B.0 06 (out) LCD EN
    ; B.1 07 (i2c) SDA
    ; B.2 08 (out) LCD RS
    ; B.3 09 (N/A) Not used
    ; B.4 10 (i2c) SCL
    ; B.5 11 (N/A) Not used
    ; B.6 12 (N/A) Not used
    ; B.7 13 (N/A) Not used
    Device = 16F819 ;set device hardware type

    XTAL = 4 ;Clock freq and type
    ALL_DIGITAL true ;All Port A pins digital

    Declare OPTIMISER_LEVEL = 0 ;Set optimizer level, 0=none
    Declare LCD_TYPE = 0 ;LCD is Alpha
    Declare LCD_DTPIN = PORTA.0 ;LCD data line starting
    Declare LCD_ENPIN = PORTB.0 ;LCD EN line
    Declare LCD_RSPIN = PORTB.2 ;LCD RS line
    Declare LCD_INTERFACE = 4 ;LCD 4 line interface
    Declare LCD_LINES = 2 ;LCD number of display lines

    Declare SDA_PIN PORTB.1 ;i2c buss SDA
    Declare SCL_PIN PORTB.4 ;i2c buss SCL
    Declare SLOW_BUS On ;12c bus 100Khz

    Symbol null = 0
    Symbol LCDdelay = 5 ;LCD control settle delay
    Symbol SSPIF PIR1.3 ;SSP (I2C) interrupt flag
    Symbol BF SSPSTAT.0 ;SSP (I2C) Buffer Full
    Symbol R_W SSPSTAT.2 ;SSP (I2C) Read/Write
    Symbol D_A SSPSTAT.5 ;SSP (I2C) Data/Address
    Symbol CKP SSPCON.4 ;SSP (I2C) SCK Release Control
    Symbol SSPEN SSPCON.5 ;SSP (I2C) Enable
    Symbol SSPOV SSPCON.6 ;SSP (I2C) Receive Overflow Indicator
    Symbol WCOL SSPCON.7 ;SSP (I2C) Write Collision Detect

    Dim buff As Byte ;Data buffer

    Init: ;* * * Init routines * * *
    SSPADD = 8 ;Make our address 8
    SSPCON = $36 ;Set to I2C slave with 7-bit address
    GoSub Banner
    buff = null ;Clear arrry and buffer

    Begin: ;* * * Mainline BEGIN * * *

    If SSPIF = 1 Then ;Check for I2C interrupt
    GoSub i2cSlave

    SSPOV = 0 ;Clear collisions & error flags
    WCOL = 0

    If buff != 0 Then ;Print byte to LCD
    Print buff
    buff = 0 ;Clear Buff

    GoTo Loop ;Do it all forever

    Stop ;* * * Mainline END * * *

    i2cSlave: ;I2C slave subroutine
    SSPIF = 0 ;Clear interrupt flag
    If R_W = 1 Then i2cTX ;Write data TO bus
    If BF = 0 Then Return ;Nothing in buffer so exit
    If D_A = 1 Then i2cRX ;Data FROM bus (not address)
    If SSPBUF != 2 Then Return ;Clear the address from the buffer

    i2cRX: ;I2C Read Data From bus
    buff = SSPBUF ;Put data into SSPBUF from buff

    i2cTX: ;I2C Write Data To bus
    SSPBUF = buff ;Put data into buff
    CKP = 1 ;Release SCL line

    Print $fe,1
    DelayMS LCDdelay
    Print " * i2cLCD101 *"
    Print $fe,$c0
    Print "LCD Addr:",@SSPADD
    DelayMS 5000
    Print $fe,1
    DelayMS LCDdelay

    If you have questions I may be reached at:

    <sigridco> <AT> <neo.> <rr.> <com>

    Sorry for the 'assemble it yourself' address but I'm trying to cut down on the spam.

    contributed by Eric J Marang.