The MCC code generates an interrupt function with a rather large else {} statement that it will enter on STOP as well as when BYTE RECEIVED and call WRITE_COMPLETE.
The receive code was changed to:
void I2C1_ISR(void)
{
uint8_t I2C1_data = 0x55;
unsigned char byte_received = 0; // new line
:
if ((I2C1STAT1bits.RXBF) || (PIR2bits.I2C1RXIF))
{
PIR2bits.I2C1RXIF = 0;
I2C1_data = I2C1RXB;
byte_received = 1;
}
:
else if ( byte_received ) // edited
{
I2C1_slaveWriteData = I2C1_data;
// callback routine should process I2C1_slaveWriteData from the master
I2C1_StatusCallback(I2C1_SLAVE_WRITE_COMPLETED);
}
else if (I2C1PIRbits.PCIF) // moved this out of the else if
{
I2C1PIR = 0;
PIR3bits.I2C1IF = 0;
I2C1STAT1bits.CLRBF = 1;
PIR3bits.I2C1TXIF = 0;
I2C1CNT = 0xFF;
}
The interrupt manager was missing interrupt for I2C error flags - not sure if this was the cause of transmit as I gave up and ended up using the following example code here:
https://mplabxpress.microchip.com/mplabcloud/example/details/519
i.e.
#include <xc.h>
#include <stdbool.h>
#include "i2c1.h"
#include "mcc.h"
#define I2C_SLAVE_ADDRESS 0x50 // this is the shifted address!
uint8_t EEPROM_Buffer[0x80] ={
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
};
uint8_t dataAddressByte = 0;
volatile uint8_t eepromAddress = 0;
void I2C1_Initialize(void)
{
I2C1ADR0 = I2C_SLAVE_ADDRESS; // Slave address
I2C1ADR1 = I2C_SLAVE_ADDRESS;
I2C1ADR2 = I2C_SLAVE_ADDRESS;
I2C1ADR3 = I2C_SLAVE_ADDRESS;
I2C1CON1 = 0x00; // CSD Clock Stretching enabled; ACKDT Acknowledge; ACKCNT Not Acknowledge;
I2C1CON2 = 0x00; // ABD enabled; SDAHT 300 ns; BFRET 8 I2C Clocks; FME disabled;
I2C1CLK = 0x00; // Slave doesn't use I2CCLK
I2C1CNT = 0x00;
I2C1CON0 = 0x00; // CSTR Enable clocking; S Cleared by hardware after Start; MODE four 7-bit address;
PIR2bits.I2C1RXIF = 0;
PIR3bits.I2C1TXIF = 0;
PIR3bits.I2C1IF = 0;
I2C1PIRbits.PCIF = 0;
I2C1PIRbits.ADRIF = 0;
PIE2bits.I2C1RXIE = 1;
PIE3bits.I2C1TXIE = 1;
PIE3bits.I2C1IE = 1;
I2C1PIEbits.PCIE = 1;
I2C1PIEbits.ADRIE = 1;
I2C1CON0bits.EN = 1;
}
void I2C1_ISR(void)
{
if ((PIR3bits.I2C1IF == 1) || (PIR2bits.I2C1RXIF == 1) || (PIR3bits.I2C1TXIF == 1))
{
if (I2C1STAT0bits.SMA == 1)
{
if (I2C1STAT0bits.R == 1)
{
if ((I2C1PIRbits.ADRIF == 1) && (I2C1STAT0bits.D == 0))
{
I2C1CNT = sizeof (EEPROM_Buffer);
I2C1PIRbits.ADRIF = 0;
I2C1PIRbits.SCIF = 0;
I2C1CON0bits.CSTR = 0;
if (I2C1STAT1bits.TXBE == 1)
{
I2C1TXB = EEPROM_Buffer[eepromAddress++];
}
}
if ((PIR3bits.I2C1TXIF == 1) && (I2C1STAT0bits.D == 1))
{
if (I2C1CNT)
{
if (eepromAddress < sizeof (EEPROM_Buffer))
{
I2C1TXB = EEPROM_Buffer[eepromAddress++];
}
else
{
eepromAddress = 0;
I2C1TXB = EEPROM_Buffer[eepromAddress++];
}
}
else
{
eepromAddress = 0;
}
I2C1CON0bits.CSTR = 0;
}
}
if (I2C1STAT0bits.R == 0)
{
if ((I2C1PIRbits.ADRIF == 1) && (I2C1STAT0bits.D == 0))
{
I2C1PIRbits.ADRIF = 0;
I2C1PIRbits.SCIF = 0;
I2C1PIRbits.WRIF = 0;
I2C1STAT1bits.CLRBF = 1;
I2C1CON0bits.CSTR = 0;
}
if ((PIR2bits.I2C1RXIF == 1) && (I2C1STAT0bits.D == 1))
{
if (dataAddressByte == 0)
{
eepromAddress = I2C1RXB;
I2C1PIRbits.WRIF = 0;
dataAddressByte = 1;
}
else
{
if (eepromAddress <= sizeof (EEPROM_Buffer))
{
while (I2C1STAT1bits.RXBF == 0);
EEPROM_Buffer[eepromAddress++] = I2C1RXB;
I2C1PIRbits.WRIF = 0;
}
else
{
eepromAddress = 0;
EEPROM_Buffer[eepromAddress++] = I2C1RXB;
I2C1PIRbits.WRIF = 0;
}
}
I2C1CON0bits.CSTR = 0;
}
}
}
else
{
if (I2C1PIRbits.PCIF)
{
I2C1PIRbits.PCIF = 0;
I2C1PIRbits.SCIF = 0;
I2C1PIRbits.CNTIF = 0;
I2C1PIRbits.WRIF = 0;
I2C1STAT1bits.CLRBF = 1;
I2C1CNT = 0;
dataAddressByte = 0;
eepromAddress = 0;
}
}
}
if (PIR3bits.I2C1EIF == 1)
{
if (I2C1ERRbits.NACKIF)
{
I2C1ERRbits.NACKIF = 0;
I2C1STAT1bits.CLRBF = 1;
dataAddressByte = 0;
eepromAddress = 0;
}
}
}
Interrupt manager must also contain
if(PIE3bits.I2C1EIE == 1 && PIR3bits.I2C1EIF == 1)
{
I2C1_ISR();
}
else if(PIE3bits.I2C1IE == 1 && PIR3bits.I2C1IF == 1)
{
I2C1_ISR();
}
else if(PIE2bits.I2C1RXIE == 1 && PIR2bits.I2C1RXIF == 1)
{
I2C1_ISR();
}
else if(PIE3bits.I2C1TXIE == 1 && PIR3bits.I2C1TXIF == 1)
{
I2C1_ISR();
}
Best Answer
If you count the bytes going forth and back:
...to obtain 2 bytes the bus uses 8 bytes. So to obtain 4 bytes, the bus will use 16. Definitely, a single read - 5 bytes - is a better choice!