I am implementing a way to transfer data using I2C protocol between PIC32mx and Arduino Uno. I've decided to establish PIC as master and Arduino as slave. I passed by all the definitions and configs for the I2C in the PIC because I already have it working perfectly with a barometer. Let's consider the Arduino as one more slave in this protocol. So from the PIC master-side I have the following code
#define EEPROM_I2C_BUS I2C1
#define i2d_address 0x14
#define I2C_CLOCK_FREQ 5000
BOOL BarI2CTransmitOneByte( UINT8 data )
{
// Wait for the transmitter to be ready
while(G_RUNNING && !I2CTransmitterIsReady(EEPROM_I2C_BUS));
// Transmit the byte
if(I2CSendByte(EEPROM_I2C_BUS, data) == I2C_MASTER_BUS_COLLISION)
{
DBPRINTF("Error: I2C Master Bus Collision\n");
return FALSE;
}
// Wait for the transmission to finish
while(G_RUNNING && !I2CTransmissionHasCompleted(EEPROM_I2C_BUS));
return TRUE;
}
void BarI2CStopTransfer( void )
{
I2C_STATUS status;
// Send the Stop signal
I2CStop(EEPROM_I2C_BUS);
// Wait for the signal to complete
do
{
status = I2CGetStatus(EEPROM_I2C_BUS);
} while( G_RUNNING && !(status & I2C_STOP) );
}
BOOL BarI2CStartTransfer( BOOL restart )
{
I2C_STATUS status;
// // Send the Stop signal
// I2CStop(EEPROM_I2C_BUS);
// Send the Start (or Restart) signal
if(restart)
{
I2CRepeatStart(EEPROM_I2C_BUS);
}
else
{
// Wait for the bus to be idle, then start the transfer
while( G_RUNNING && !I2CBusIsIdle(EEPROM_I2C_BUS) );
if(I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
{
DBPRINTF("Error: Bus collision during transfer Start\n");
return FALSE;
}
}
// Wait for the signal to complete
do
{
status = I2CGetStatus(EEPROM_I2C_BUS);
} while ( !(status & I2C_START) );
return TRUE;
}
void main(){
UINT32 actualClock;
BOOL Success2 = TRUE;
actualClock = I2CSetFrequency(EEPROM_I2C_BUS, GetPeripheralClock(), I2C_CLOCK_FREQ);
if ( abs(actualClock-I2C_CLOCK_FREQ) > I2C_CLOCK_FREQ/10 )
{
//DBPRINTF("Error: I2C1 clock frequency (%u) error exceeds 10%%.\n", (unsigned)actualClock);
}
// Enable the I2C bus
I2CEnable(EEPROM_I2C_BUS, TRUE);
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, i2d_address, I2C_WRITE);
i2cData[0] = SlaveAddress.byte;
i2cData[1] = 0x03; // EEPROM location to read (high address byte)
DataSz = 2;
if( !BarI2CStartTransfer(FALSE) )
{
while(G_RUNNING && 1);
}
Index = 0;
while(Success2 & (Index < DataSz) )
{
// Transmit a byte
if (BarI2CTransmitOneByte(i2cData[Index]))
{
// Advance to the next byte
Index++;
}
else
{
Success2 = FALSE;
}
// Verify that the byte was acknowledged
if(!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
{
DBPRINTF("Error: Sent byte was not acknowledged\n");
Success2 = FALSE;
}
}
BarI2CStopTransfer();
if(Success2)
{
// Send a Repeated Started condition
if( !BarI2CStartTransfer(FALSE) )
{
while(1);
}
// Transmit the address with the READ bit set
I2C_FORMAT_7_BIT_ADDRESS(SlaveAddress, i2d_address, I2C_READ);
if (BarI2CTransmitOneByte(SlaveAddress.byte))
{
// Verify that the byte was acknowledged
if(!I2CByteWasAcknowledged(EEPROM_I2C_BUS))
{
DBPRINTF("Error: Sent byte was not acknowledged\n");
Success2 = FALSE;
}
}
else
{
Success2 = FALSE;
}
}
// Read the data from the desired address
if(Success2)
{
if(I2CReceiverEnable(EEPROM_I2C_BUS, TRUE) == I2C_RECEIVE_OVERFLOW)
{
DBPRINTF("Error: I2C Receive Overflow\n");
Success2 = FALSE;
}
else
{
while(!I2CReceivedDataIsAvailable(EEPROM_I2C_BUS));
i2cbyte = I2CGetByte(EEPROM_I2C_BUS);
}
}
BarI2CStopTransfer();
if(!Success2)
{
while( G_RUNNING && 1);
}
For the Arduino slave-side I wrote this following code:
void setup(void)
{
Wire.begin(20);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(9600); // start serial comm
}
void receiveEvent(int howMany){
int x = Wire.read();
}
void requestEvent(){
Wire.write('x');
}
void loop(){
}
So from the PIC side I am sending the byte 0x03 which I receive in the receiveEvent method in the Arduino side. At this point everything is working well. After that the requestEvent is called and the 'x' character is beeing sent to the PIC side. Now the PIC side is blocking in the DBPRINTF("Error: I2C Receive Overflow\n");
sentence which means I am taking too long to receive the 'x' byte from the Arduino side and the SDA line is never released as well.
I have pull ups in my I2C protocol at 3.3V (Master-PIC) and I trying to communicate using the A4(SDA)
and A5(SCL)
in the Slave-Arduino side which is at 5V.
I am following this Tutorial carefully and trying to replicate the "Reading from a slave" part but without success.
EDIT: I am following the procedure and I am receiving the byte properly from the arduino side however the code is locked up in the RFIDI2CStopTransfer();
in the PIC side and I don't know why. Is there someone who can help me with this issue?