#include <system.h>
#pragma CLOCK_FREQ 16000000
#pragma DATA _CONFIG1, _HS_OSC & _MCLRE_ON & _WDT_OFF
#pragma DATA _CONFIG2, _WRT_1FOURTH & _BOR21V
// Test I2C in Slave mode with mask address register.
// I2C Addresses and Commands
#define I2C_ADDRESS 0xA8
void interrupt (void)
{ if (pir1.SSPIF)
{ portc.7 = pir1.SSPIF; // mirror the SSPIF state.
portc.7 = pir1.SSPIF=0;
portc.6 = sspstat.BF;
if (sspstat.S & sspstat.BF)
// Slave receives address/data after start
portb = sspbuf;
portc.6 = sspstat.BF;
}
}
void main()
{ portc.7 = 0;
portc.6 = 0;
trisc.3 = 1; // SCL as inputs (release bus)
trisc.4 = 1; // SDA as inputs (release bus)
trisc.6 = 0; // used to flag BF bit
trisc.7 = 0; // used to mirror the state of SSPIF
portb = 0;
trisb = 0;
// Make low nibble bits as "don't care" bit address.
// This register *must be* initiated prior to setting SSPM<3:0> bits to select the I2C Slave mode (7-bit or 10-bit address).
// Note that SSPMASK coincides with SSPADD and that we should write SSPCON with 0b1001 in order to have access to it.
sspcon.SSPM0 = 1;
sspcon.SSPM1 = 0;
sspcon.SSPM2 = 0;
sspcon.SSPM3 = 1;
sspadd = 0xF0;
// Activate I2C, Slave mode, 7Bit, with Start/Stop bit interrupt
sspcon.SSPM0 = 0;
sspcon.SSPM1 = 1;
sspcon.SSPM2 = 1;
sspcon.SSPM3 = 1;
// SSPSTAT Status Register
sspstat.SMP = 0; // Slewrate Control disabled
sspstat.CKE = 0; // SMBUS specific inputs disabled
// CKP, Release Clock
sspcon.CKP = 1;
// Disable Address 0x0 General Call
sspcon2.GCEN = 1;
// Disable clock stretching
sspcon2.SEN = 0;
// Set I2C Slave address
sspadd = I2C_ADDRESS;
// Synchronous Serial Port Enable
sspcon.SSPEN = 1;
// dummy read clears BF
unsigned int dummy = sspbuf;
// Clear Buffer Overflow
sspcon.SSPOV = 0;
// Receive Enable
sspcon2.RCEN = 1;
// Enable Global, Peripheral and SSP module interrupts
intcon.GIE = 1;
intcon.PEIE = 1;
pie1.SSPIE = 1;
// do it forever
while(1) ;
}