16F877 MSSP module as I2C







#define  ack    pir1,sspif

tst_ack  macro                ;test pir1,sspif
         bank0
         btfss  ack
         goto   $-1
         bcf    ack           ;clear sspif
         endm

         bank1                ;SCL and SDA as inputs
         movlw  b'00011000'
         movwf  tris
         bank0
         clrf   portc

;================================================
;        I2C setup
;================================================

         bank1
         clrf   sspstat
         bsf    sspstat,smp   ;disable slew for 100kHz comms
         bcf    sspstat,cke   ;normal I2C
         bank0

         movlw  b'00101000'

;                   1          Enable PortC as I2C
;                    0         Enable clock
;                     1000     Master mode, sspm3:2:1:0 = 1000
;                              Clock = 4 * (SSPADD+1)
         movwf  sspcon

         bank1
         movlw  .45           ;set clock rate for 100kHz
         movwf  sspadd        ; ((18,432,000/100,000)/4)-1 = 45

         bank0                ;wait for switch push / release 
         btfsc  pbgo
         goto   $-1
         btfss  pbgo
         goto   $-1

;================================================
;        Write 173d to EEPROM address 0a23
;================================================

         bank1
         bsf    sspcon2,sen   ;send start bit
         bank0
         tst_ack              ;test and clear sspif

;---------------

         movlw  b'10101000'   ;send device address, 1010 + 100 + Write
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         movlw  0x0a          ;send memory address MSB
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         movlw  0x23          ;send memory address LSB
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         movlw  .173          ;send data
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         bank1
         bsf    sspcon2,pen   ;send Stop bit
         bank0
         btfss  pir1,sspif
         goto   $-1
         bcf    pir1,sspif

;---------------

         movlw  0x14          ;20ms delay
         movwf  temp
         call   msdelay
         decfsz temp,f
         goto   $-2   

;================================================
;        Read EEPROM address 0a23
;================================================

         bank1
         bsf    sspcon2,sen   ;send Start bit
         bank0
         tst_ack

;---------------

         movlw  b'10101000'   ;send device address, 1010 + 100 + Write
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         movlw  0x0a          ;send memory address MSB
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         movlw  0x23          ;send memory address LSB
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         bank1
         bsf    sspcon2,pen   ;send Stop bit
         bank0
         btfss  pir1,sspif
         goto   $-1
         bcf    pir1,sspif

;---------------

         bank1
         bsf    sspcon2,sen   ;send Start bit
         bank0
         tst_ack

;---------------

         movlw  b'10101001'   ;send device address, 1010 + 100 + Read
         movwf  sspbuf

;---------------

         tst_ack

;---------------

         bank1
         bsf    sspcon2,rcen  ;set PIC as receiver
         bank0

;---------------

         btfss  pir1,sspif    ;receive buffer full ?
         goto   $-1
         bank1
         bsf    sspcon2,ackdt ;NACK
         bsf    sspcon2,acken ;initiate NACK sequence
         bank0
         bcf    pir1,sspif

;---------------

         movf   sspbuf,w      ;read / clear buffer
         movwf  temp

;---------------

         tst_ack

;---------------

         bank1
         bsf    sspcon2,pen   ;send Stop bit
         bank0
         btfss  pir1,sspif
         goto   $-1
         bcf    pir1,sspif

         call   bin2bcd       ;convert to 3-digits
         call   show_num      ;and display

i2cend   goto   i2cend