I am writing a basic I2C slave as part of my code on a 20-pin 8-bit PIC16f MCU. As best as I can tell, this microcontroller has a module that watches the I2C bus and only updates my registers if there are incoming message addressed to the PIC -- I can't interact with any other messages. The master is a CPU running a linux kernel and some other software. From the CPU, I can run a I2C probe script that just tries to read from every possible device address on the I2C chain (bus).
I'm having trouble getting the PIC to respond to any probing. I've written the simplest I2C code I can manage -- it should just blink the LEDs whenever the device gets any sort of I2C message directed at it.
I hooked the lines up to the oscilloscope and was able to confirm that traffic is coming through the clock and data lines when I probe the chain.
My code is below. My compiler is the free version (without optimizations) of Microchip's XC8. I'm using the newest version (v1.34) for Windows.
Am I missing any initialization or configuration steps necessary to get my PIC to see incoming I2C messages?
#include <xc.h> /* XC8 General Include File */
#include <pic16lf1709.h> /* Definitions of I/O pins */
#pragma config WDTE = OFF // disable watchdog timer, for simplicity
// I2C address is 7 bits: 1111110
#define I2C_ADDRESS 0x7E
typedef unsigned char byte;
void main(void) {
/* configure MSSP module */
TRISBbits.TRISB4 = 1; // set SDA to input
TRISBbits.TRISB6 = 1; // set SCL to input
SSPCON1bits.SSPEN = 1; // enable SSP module
SSPCON1bits.SSPM = 0x6; // SSP is in I2C slave mode, 7-bit addressing
SSP1ADD = I2C_ADDRESS<<1; // set the device address (left-aligned)
SSPCON1bits.CKP = 1; // release clock
TRISC = 0x00; // set LEDs to output
PORTC = 0xFF; // initialize LEDs to OFF
while(1) {
byte ssp_buf; // for the data we read from the bus
if(SSPSTATbits.BF) { // if the I2C buffer is not empty
PORTC = 0x00; // turn on LEDs for a moment
for(int i=0; i<100; i++) _delay(250);
PORTC = 0xFF; // turn them back off
ssp_buf = SSPBUF; // read the buffer
// BF flag is cleared by hardware
}
SSPCON1bits.CKP = 1; // finally, release clock
}
}
counter
which increments +1 eachwhile
iteration. Toggle the LED on (and resetcounter
) whenever data is received, but only toggle it off after 10,000 while-loops have commenced. \$\endgroup\$