protocolo I2C entre PIC32mx y Arduino Uno

1

Estoy implementando una forma de transferir datos usando el protocolo I2C entre PIC32mx y Arduino Uno. Decidí establecer PIC como maestro y Arduino como esclavo . Pasé por todas las definiciones y configuraciones para el I2C en el PIC porque ya lo tengo funcionando perfectamente con un barómetro. Consideremos al Arduino como un esclavo más en este protocolo. Así que desde el lado del maestro PIC tengo el siguiente código

#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);
}

Para el Arduino del lado del esclavo, escribí este siguiente código:

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(){
}

Entonces, desde el lado PIC, estoy enviando el byte 0x03 que recibí en el método receiveEvent en el lado Arduino. En este punto todo está funcionando bien. Después de eso, se llama al requestEvent y se envía el carácter 'x' al lado PIC. Ahora, el lado PIC está bloqueando en la oración DBPRINTF("Error: I2C Receive Overflow\n"); , lo que significa que estoy tardando demasiado en recibir el byte 'x' del lado Arduino y la línea SDA nunca se libera también.

Tengo pull ups en mi protocolo I2C a 3.3V ( Master-PIC ) y trato de comunicarme usando A4(SDA) y A5(SCL) en Slave-Arduino Tutorial con cuidado y tratando de replicar la parte "Leer de un esclavo" pero sin éxito.

EDITAR: estoy siguiendo el procedimiento y recibo el byte correctamente del lado arduino, sin embargo, el código está bloqueado en el RFIDI2CStopTransfer(); en el lado PIC y no sé por qué. ¿Hay alguien que pueda ayudarme con este problema?

    
pregunta scuba

1 respuesta

1

Parte del problema estaba relacionado con la dirección que he usado para comunicarme con el Arduino. Estaba usando 0x07 como dirección pero está reservada, así que cambié a 0x14 (20 en decimal). Sin embargo, he editado la publicación para obtener ayuda con este nuevo problema.

    
respondido por el scuba

Lea otras preguntas en las etiquetas