Estoy trabajando en una placa de desarrollo PIC32-MAXI-WEB de Olimex que me gustaría comunicarme con un acelerómetro / giroscopio Invensense MPU-6050 6DOF. Al modificar una demo de Olimex, logré que la imagen se comunicara.
Comencé a trabajar en un proyecto para el que creé un nuevo proyecto (en IDE), ya que no necesitaba / quería el kernel FreeRTOS en el que se basa la demostración. Sin embargo, no puedo hacer que el mismo código I2C funcione allí. Obtengo algunos resultados, pero no lo que debería obtener.
Funciones de ayuda de la DEMO de Olimex:
BOOL StartTransfer( BOOL restart )
{
I2C_STATUS status;
// Send the Start (or Restart) signal
if(restart)
{
I2CRepeatStart(I2C2);
}
else
{
// Wait for the bus to be idle, then start the transfer
while( !I2CBusIsIdle(I2C2) );
if(I2CStart(I2C2) != I2C2)
{
DBPRINTF("Error: Bus collision during transfer Start\n");
return FALSE;
}
}
// Wait for the signal to complete
do
{
status = I2CGetStatus(I2C2);
} while ( !(status & I2C_START) );
return TRUE;
}
BOOL TransmitOneByte( UINT8 data )
{
// Wait for the transmitter to be ready
while(!I2CTransmitterIsReady(I2C2));
// Transmit the byte
if(I2CSendByte(I2C2, data) == I2C_MASTER_BUS_COLLISION)
{
DBPRINTF("Error: I2C Master Bus Collision\n");
return FALSE;
}
// Wait for the transmission to finish
while(!I2CTransmissionHasCompleted(I2C2));
return TRUE;
}
void StopTransfer( void )
{
I2C_STATUS status;
// Send the Stop signal
I2CStop(I2C2);
// Wait for the signal to complete
do
{
status = I2CGetStatus(I2C2);
} while ( !(status & I2C_STOP) );
}
Mi código:
int I2C_CLOCK_SPEED = 400000;
int actualClock;
// Configure Various I2C Options
I2CConfigure(I2C2, 0);
// Set Desired Operation Frequency
actualClock = I2CSetFrequency(I2C2, GetPeripheralClock(), I2C_CLOCK_SPEED);
if ( abs(actualClock-I2C_CLOCK_SPEED) > I2C_CLOCK_SPEED/10 ) {
return -1;
}
// Enable the module
I2CEnable(I2C2, TRUE);
BYTE ADDR = 0x68<<1;
BIT WRITE = 0;
BIT READ = 1;
BYTE tmp;
StartTransfer(FALSE); // Read power management register
TransmitOneByte(ADDR|WRITE);
TransmitOneByte(0x75);
StartTransfer(TRUE);
TransmitOneByte(ADDR |READ);
I2CReceiverEnable(I2C2, TRUE);
while(!I2CReceivedDataIsAvailable(I2C2));
I2CAcknowledgeByte(I2C2, FALSE);
tmp = I2CGetByte(I2C2);
StopTransfer();
Con un analizador lógico puedo ver que parece eliminar la dirección y enviar solo el segundo byte de los tres. También falla al enviar el bit de parada / devolver el bus a inactivo:
No debería ser un problema de hardware, ya que la demostración original funciona. Estoy usando el compilador xc32 y MPLAB X IDE.