This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LAUNCHXL-F28069M: request by I2C to Gyro sensor - I2CDRR never ready to be read

Part Number: LAUNCHXL-F28069M
Other Parts Discussed in Thread: MOTORWARE

Hi,


I'm using gyro sensor MPU-6050 https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf

In my code I try to request data of gyro readings at 0x3B, and 0x3C registers, but program always stuck in line:

            while(I2caRegs.I2CSTR.bit.RRDY == 0){};     //I2CDRR not ready to read?

It means data has not been copied from I2CRSR to I2CDRR, but I dont have idea why.

Could you check my code please?



#include "DSP28x_Project.h"
#include <stdio.h>


Uint16 PassCount;
Uint16 FailCount;
Uint16 Data[]={0x6B,0x3B};
Uint16 RxdData[10];


void main(void)
{
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2806x_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Setup only the GP I/O only for I2C functionality
    //
    InitI2CGpio();

    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //
    DINT;

    //
    // Initialize PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2806x_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Disable CPU interrupts and clear all CPU interrupt flags
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2806x_DefaultIsr.c.
    // This function is found in F2806x_PieVect.c.
    //
    InitPieVectTable();


    PassCount = 0;
    FailCount = 0;

    //
    // Enable interrupts required for this example
    //

    //
    // Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
    //
    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

    //
    // Enable CPU INT8 which is connected to PIE group 8
    //
    IER |= M_INT8;
    EINT;

	
	
    //////////////////////////
    // Write data to EEPROM //
    //////////////////////////

    I2caRegs.I2CSAR = 0x68;            				//Set slave address
    I2caRegs.I2CCNT = 2;          					//Set count to 5 characters plus 2 address bytes
    I2caRegs.I2CDXR = 0x6B;							//register where i will write 0x40 (reset)
    I2caRegs.I2CMDR.bit.TRX = 1;               		//Set to Transmit mode
    I2caRegs.I2CMDR.bit.MST = 1;          	     	//Set to Master mode
    I2caRegs.I2CMDR.bit.FREE = 1;           	  	//Run in FREE mode
    I2caRegs.I2CMDR.bit.STP = 1;            	    //Stop when internal counter becomes 0
    I2caRegs.I2CMDR.bit.STT = 1;           	     	//Send the start bit, transmission will follow

    while(I2caRegs.I2CSTR.bit.XRDY == 0){};     	//Do nothing till data is shifted out
    I2caRegs.I2CDXR = 0x40;

    for(i = 0; i < 3; i++){
        RxdData[i] = 0x00;
    }

    for(;;)
    {

		//////////////////////////
		// Read data from EEPROM//
		//////////////////////////
		
        //while(I2caRegs.I2CSTR.bit.XRDY == 0){};      //Do nothing till data is shifted out
        I2caRegs.I2CSAR = 0x68;                      //Set slave address
        I2caRegs.I2CCNT = 1;                         //Set count to 2 address bytes
        I2caRegs.I2CDXR = 0x3B;                      //Send high address of register to read
        I2caRegs.I2CMDR.bit.TRX = 1;                 //Set to Transmit mode
        I2caRegs.I2CMDR.bit.MST = 1;                 //Set to Master mode
        I2caRegs.I2CMDR.bit.FREE = 1;                //Run in FREE mode
        I2caRegs.I2CMDR.bit.STP = 0;                 //Dont release the bus after Tx
        I2caRegs.I2CMDR.bit.STT = 1;                 //Send the start bit, transmission will follow

        while(I2caRegs.I2CSTR.bit.XRDY == 0){};      //Do nothing till data is shifted out
        //I2caRegs.I2CDXR = 0x3B;                      //Send low address of register to read
        //while(I2caRegs.I2CSTR.bit.XRDY == 0){};      //Do nothing till data is shifted out
        I2caRegs.I2CCNT = 2;                         //read 5 bytes from eeprom
        I2caRegs.I2CMDR.bit.TRX = 0;                 //Set to Recieve mode
        I2caRegs.I2CMDR.bit.MST = 1;                 //Set to Master mode
        I2caRegs.I2CMDR.bit.FREE = 1;                //Run in FREE mode
        I2caRegs.I2CMDR.bit.STP = 1;                 //Stop when internal counter becomes 0
        I2caRegs.I2CMDR.bit.STT = 1;                 //Repeated start, Reception will follow
		
        for(i = 0; i < 2; i++){
             while(I2caRegs.I2CSTR.bit.RRDY == 0){};     //I2CDRR not ready to read?   program stuck here in endless loop
             RxdData[i] = I2caRegs.I2CDRR;
             PassCount++;
        }


    }
}



  • Hi Wojciech,

    Looks like you've made some good progress. Being that you're working off the i2c_eeprom example, which uses the I2C FIFO, you're likely experiencing some minor nuances between that and your program which is not using the I2C FIFO.

    Do you have a I2C logic analyzer or oscilloscope handy so you can probe the signals and verify the data? It'd be a good first step to check that the first I2C transmit is completing successfully. It should look like:

    START condition --> I2C Slave Address + ACK --> Command Byte (0x3B) + ACK --> STOP condition

    Feel free to share any waveforms you collect here.

    Maybe the slave address is incorrect? The WHO_AM_I register on your slave device could verify this for you.

    Best,
    Kevin
  • Hi Kevin,

    Thank You for your quick response.

    About FIFO mode - I'm working on 2c_eeprom example, but I remove I2CA_Init() function, which contained I2CFFTX and I2CFFRX registers setup. 

    I also check I2CFFTX and I2CFFRX registers in watchwindow while program was running - all bits remains zeros.

    I double check slave address by arduino echo program, and arduino WHO_AM_I register read, and connect AD0 pin to ground to make sure that it does not take a random value. (Ad0 changes 0x68 to 0x69 when is in high state)

    I'm little confused about setting 0x6B register to zero. I find it in arduino gyro setup example :

      Wire.write(0x6B); // PWR_MGMT_1 register
      Wire.write(0); // set to zero (wakes up the MPU-6050)

    They write that setting this register to zero wakes up the sensor. Maybe it will be better to reset sensor by setting bit7 to 1?  

    Register HEX Register DEC bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
    6B 107 Device_reset sleep cycle - temp_dis clk_sel clk_sel clk_sel

    (MPU-6000/MPU-6050 Register Map page 45, link in previous post)

    I bought the logic state analyzer, I will get it tomorrow and check bus signals.

    Best Regards,

    Wojciech

  • Hi Wojchiech,

    Yes, I was just pointing out that it looked like you opted to not use FIFO mode and that there will be some differences from a software standpoint in comparison to the i2c_eeprom example because of it. The FIFO registers being zeroed out makes sense because of this.

    The slave address sounds right then.

    Setting the 0x6B register to zero is likely intended and correct. The comment "set to zero (wakes up the MPU-6050)" is just meaning the sleep bit (bit 6) is getting set to zero, which wakes up the device. You don't necessarily want to reset the device.

    That's good that you're investing in a logic analyzer, that should help in debugging and understanding the communication a lot. If the Arduino program you are running works as intended, it would be a good idea to look at the logic of the I2C bus when running it. Then you could use the waveforms as a basis for your C2000 I2C comms and try to replicate it.

    Best,
    Kevin
  • Hi,

    I worked a few days with logic analyzer and solved the problem

    Arduino communication looked fine, but when i run my program there was no action, both scl and sda remains in high state.

    It worked when i remove interrupts code:

        PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
    
        //
        // Enable CPU INT8 which is connected to PIE group 8
        //
        IER |= M_INT8;
        EINT;

    Another problem was speed of transmission. It was too high i think (400kbps). I change I2caRegs.I2CPSC.all (prescaler) to 35, so now i have 100kbps.

    I also added delays between transmissions.

    Now i have working code, but there is another issue - how to migrate that code to motorware project?