Update: 3 May 2003

As part of a class project I've taken it upon myself to convert these i2c
routines into a general purpose I2C template for devices containing the
I2C module. I expect to produce a general purpose template within the next few days using John Sands original code.

--Matt Krutar


PIC Microcontoller Input / Output Methods for I2C on 16F87x

by John Sand [jsand at PIXIE.CO.ZA]

I cribbed, borrowed and stole whatever I could, then went back to the 16f87x manual and wound up with a set of master transmit <> receive routines that are *working* - perfectly well as far as I can tell.

This app. has two Philips PCF8574 I2C general purpose byte-wide IO port chips. One (IO1) is dedicated to inputs only, for switch states, etc., while IO2 is output only, to drive a collection of panel LEDs. I have used private macros like :-


        bank0        ;use ram bank0
        bank1        ;use ram bank1
        movlf           ;load literal to freg
        movff            ;load freg1 to freg2

etc., these should need no introduction, but if they do, let me know.. Setup the ports by :-

        setup_i2c

Invoke a IO1 port read by:-

        read_switches      ;byte-wide result in freg`latest_switch_state'

Invoke a IO2 port write by:-

                                                ;put desired byte into freg
'led_state'
        write_leds
;****************** I2C macros begin
start_i2c         MACRO              ;[S]
     bank0                                     ;bank0 (bank0? names) be sure
     bcf             PIR1,SSPIF
     bank1                                           ;bank1
     bsf             SSPCON2,SEN     ;send i2c START [S] bit
     bank0                                       ;bank0
     btfsS         PIR1,SSPIF         ;start bit cycle complete?
     goto         $-1
       endm

enable_receive_i2c     MACRO
     bank1                                           ;bank1
     bsf             SSPCON2,RCEN     ;enable receiving at master 16f877
     bank0                                           ;bank0
     bcf             PIR1,SSPIF
     btfsS         PIR1,SSPIF             ;sspbuf buffer full byte?
     goto             $-1
       endm

stop_i2c         MACRO                  ;[P]
     bank0                                           ;bank0
     bcf             PIR1,SSPIF
     bank1                                           ;bank1
     bsf             SSPCON2,PEN         ;send i2c STOP [P] bit
     bank0                                           ;bank0
     btfsS         PIR1,SSPIF             ;stop bit cycle completed?
     goto         $-1
           endm

wait_for_ack_i2c         MACRO
     bank0                                           ;bank0
     bcf             PIR1,SSPIF
     btfsS         PIR1,SSPIF                 ;ACK received?
     goto         $-1
       endm

setup_i2c         MACRO                          ;setup mssp for i2c
     movlf         00101000b,SSPCON     ;=0x028
     bank1
     movlf         10000000b,SSPSTAT
     movlf         01100000b,SSPCON2
     movlf         00001010b,SSPADD
     bank0
       endm

read_switches     MACRO                   ;io1 is inputs only
     start_i2c
     movlf             01000011b,SSPBUF     ;send out io1 pcf8574 addr
     wait_for_ack_i2c
     enable_receive_i2c
     movff             SSPBUF,latest_switch_state
     stop_i2c
       endm

write_leds MACRO                                   ;io2 is output only
     start_i2c
     movlf             01000100b,SSPBUF                 ;sned out io2
address, writing
     wait_for_ack_i2c
     movff             led_state,SSPBUF
     wait_for_ack_i2c
     stop_i2c
       endm
;***************** I2C macros end


Comments: