3 Slave Mode Code Example
MSSP in I2C Slave Mode shows the use of the MSSP in 7-bit I2C Slave mode. The example uses an Interrupt Service Routine (ISR) to determine whether the master intends to read data from or write data to the slave, and react accordingly. A PICkit™ Serial Analyzer tool, which includes a graphical user interface (GUI), was used as the master device for simplicity. The GUI allows a user to read data from or write data to specific address locations within the slave.
MSSP in I2C Slave Mode
#define ARRAY_CNT 32 // Number of bytes in array uint8_t slaveAddress = 0x30; // 7-bit slave address uint8_t index = 0; // Array pointer uint8_t temp = 0; // Temp register uint8_t regAdd = 1; // First data byte was reg add uint8_t i2cArray[ARRAY_CNT] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFA, 0xEA, 0xDA, 0xCA, 0xBA, 0xFB, 0xFC, 0xFD, 0xFE, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; void I2C_Initialize(void) { SSP1STATbits.SMP = 1; // Disable slew control SSP1CON1bits.SSPM = 0b0110; // 7-bit slave mode SSP1CON2bits.SEN = 1; // Enable clock stretching SSP1CON3bits.SBCDE = 1; // Enable BCLIF SSP1ADD = slaveAddress; // Load slave address SSP1CON1bits.SSPEN = 1; // Enable the module PIR3bits.BCL1IF = 0; // Clear Bus Collision IF PIR3bits.SSP1IF = 0; // Clear SSP interrupt flag PIE3bits.BCL1IE = 1; // Enable BCLIF PIE3bits.SSP1IE = 1; // Enable SSPIF INTCONbits.PEIE = 1; // Enable periph interrupts INTCONbits.GIE = 1; // Enable global interrupts } void __interrupt() ISR(void) { if(PIR3bits.SSP1IF) // Check for SSPIF { if(SSP1STATbits.R_nW == 1) // Master read (slave transmit) { SSP1BUF = i2cArray[index++]; // Load array value SSP1CON1bits.CKP = 1; // Release clock stretch } if(SSP1STATbits.R_nW == 0) // Master write (slave receive) { if(SSP1STATbits.D_nA == 0) // Last byte was an address { regAdd = 1; // Next byte register address temp = SSP1BUF; // Clear BF SSP1CON1bits.CKP = 1; // Release clock stretch } if(SSP1STATbits.D_nA == 1) // Last byte was data { if(regAdd == 1) // Last byte was register add { index = SSP1BUF; // Load register address regAdd = 0; // Next byte will be true data } else { if(index < ARRAY_CNT) // Within boundaries? { i2cArray[index++] = SSP1BUF; // Yes, read SSP1BUF } else { temp = SSP1BUF; // No, discard data } } SSP1CON1bits.CKP = 1; // Release clock stretch } } } if(PIR3bits.BCL1IF == 1) { temp = SSP1BUF; // Clear BF PIR3bits.BCL1IF = 0; // Clear BCLIF SSP1CON1bits.CKP = 1; // Release clock stretching } PIR3bits.SSP1IF = 0; // Clear SSP1IF }