Hello,
I use the following code to try to communicate with the MPU6050 sensor:
//////////////////////////////////////////////////////////////////////////////////////////////////// #include <stdbool.h> #include <stdint.h> #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/pwm.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" #include "inc/hw_gpio.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include <stddef.h> // For using the NULL pointer #define PWM_FREQUENCY 55 //////////////////////////////////////////////////////////////////////////////////////////////////// // My I2C defines & includes #include "driverlib/i2c.h" #include "driverlib/interrupt.h" #include "inc/hw_i2c.h" #include "inc/hw_ints.h" #include "sensorlib/i2cm_drv.h" #include "sensorlib/mpu6050.h" #include "sensorlib/hw_mpu6050.h" #define DEBUG //////////////////////////////////////////////////////////////////////////////////////////////////// // My UART defines & includes #include "driverlib/uart.h" #include "utils/uartstdio.h" //////////////////////////////////////////////////////////////////////////////////////////////////// #include "definitions_mpu6050.h" tI2CMInstance g_sI2CInst; // I2C master driver structure. "tI2CMInstance" is defined in the i2cm_drv.h file. tMPU6050 g_sMPU6050Inst; // MPU6050 sensor driver structure. "tMPU6050" is defined in the mpu6050.h file. volatile unsigned long g_vui8DataFlag; // Data ready flag volatile unsigned long g_vui8ErrorFlag; // Error flag void ISL29023I2CIntHandler(void) { I2CMIntHandler(&g_sI2CInst); } //////////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { // Configure the clock SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); //////////////////////////////////////////////////////////////////////////////////////////////////// // My I2C initialization code // Enable GPIO peripheral that contains I2C 2 // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // Enable I2C module 2 // SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C3); SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2); // Configure the pin muxing for I2C2 functions on port E4 and E5. // GPIOPinConfigure(GPIO_PD0_I2C3SCL); // GPIOPinConfigure(GPIO_PD1_I2C3SDA); GPIOPinConfigure(GPIO_PE4_I2C2SCL); GPIOPinConfigure(GPIO_PE5_I2C2SDA); // Select the I2C function for these pins. // GPIOPinTypeI2CSCL(GPIO_PORTD_BASE, GPIO_PIN_0); // GPIOPinTypeI2C(GPIO_PORTD_BASE, GPIO_PIN_1); GPIOPinTypeI2CSCL(GPIO_PORTE_BASE, GPIO_PIN_4); GPIOPinTypeI2C(GPIO_PORTE_BASE, GPIO_PIN_5); IntMasterEnable(); // I2CMInit(&g_sI2CInst, I2C3_BASE, INT_I2C3, 0xFF, 0xFF, SysCtlClockGet()); I2CMInit(&g_sI2CInst, I2C2_BASE, INT_I2C2, 0xFF, 0xFF, SysCtlClockGet()); SysCtlDelay(SysCtlClockGet() / 3); float fAccel[3], fGyro[3]; // USER_MPU6050Callback will modify the g_bMPU6050Done variable to true if MPU6050Init succeeds. g_bMPU6050Done = false; // Initialize the MPU6050 MPU6050Init(&g_sMPU6050Inst, &g_sI2CInst, MPU6050_I2C_ADDRESS, USER_MPU6050Callback, &g_sMPU6050Inst); while(!g_bMPU6050Done) { } // USER_MPU6050Callback will modify the g_bMPU6050Done variable to true if MPU6050ReadModifyWrite succeeds. g_bMPU6050Done = false; // Configure the MPU6050 for +/- 4 g accelerometer range. MPU6050ReadModifyWrite(&g_sMPU6050Inst, MPU6050_O_ACCEL_CONFIG, ~MPU6050_ACCEL_CONFIG_AFS_SEL_M, MPU6050_ACCEL_CONFIG_AFS_SEL_4G, USER_MPU6050Callback, &g_sMPU6050Inst); while(!g_bMPU6050Done) { } while(1) { // USER_MPU6050Callback will modify the g_bMPU6050Done variable to true if MPU6050DataRead succeeds. g_bMPU6050Done = false; // Request another reading from the MPU6050. MPU6050DataRead(&g_sMPU6050Inst, USER_MPU6050Callback, 0); while(!g_bMPU6050Done) { } // Get the new accelerometer and gyroscope readings. MPU6050DataAccelGetFloat(&g_sMPU6050Inst, &fAccel[0], &fAccel[1], &fAccel[2]); MPU6050DataGyroGetFloat(&g_sMPU6050Inst, &fGyro[0], &fGyro[1], &fGyro[2]); } }
I run the code step by step using F6 and get to the MPU6050Init function.
When this function is called I see (using an oscilloscope) the SDA and SCL I2C lines toggle correctly and the MPU6050 acknowledge to address 0x68.
However, when the transaction is finished the MPU6050 holds the SCL line low and doesn't release it.
According to the I2C specifications - this signifies that the device is serving an interrupt. Only in my case it continues forever.
When I proceed with F6 to the MPU6050ReadModifyWrite function is called and completed - but then when I press F6 again the code gets stuck in the while(!g_bMPU6050Done) { } condition.
Is it possible that MPU6050Init doesn't release the device from reset ?
Similarly to what mentioned in this post: