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: I2C Communication Issue in Motorware.

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

Hello all,

I've been trying to get i2C communications working with the above mentioned uC in the Motorware Instaspin labs.

I managed to find I2C drivers online and I thought I had a the ability to write data figured out. Unfortunately, the success was mixed. Sometimes I couldn't get any output on the I2C lines at all, other times it worked, and oddly sometimes the bits in the slave and data bytes would all be shifted to the right by one. After making various changes I can longer even get that. The I2C lines just stay high.

I believe the setup code is working as expected and that the issue is in my write function. If I comment it out the device no longer hangs in the "Idle" state and the motor run as normal. When looking at the registers (they don't change), the I2CSTR is 0x0420, and the MDR register is 0x0220. The only thing i can think of worth noting in this is that the SCD bit is set.

I'll include all of the files I changed (hal, i2c, etc.) just in case it helps. I2CCode.zip

Here is the write function as I believe it is the culprit:

void accel_Write(HAL_Handle halHandle, uint16_t register_add, uint16_t data ){


    while(I2C_isMasterBusy(halHandle->i2cHandle));
    I2C_clearStopConditionDetection(halHandle->i2cHandle);
    while(I2C_isMasterStopBitSet(halHandle->i2cHandle));


    while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
    // If a NACK occurred, SCL is held low and STP bit cleared
    if ( I2C_isNoAck(halHandle->i2cHandle) )
    {
        I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
        I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
    }
    I2C_putData(halHandle->i2cHandle, register_add);
    I2C_MasterControl(halHandle->i2cHandle, I2C_Control_Single_TX, 0, 2);
    //while(I2C_isMasterBusy(halHandle->i2cHandle));

//    while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
//    // If a NACK occurred, SCL is held low and STP bit cleared
//    if ( I2C_isNoAck(halHandle->i2cHandle) )
//    {
//        I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
//        I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
//    }
//    I2C_putData(halHandle->i2cHandle, register_add);

    while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
    // If a NACK occurred, SCL is held low and STP bit cleared
    if ( I2C_isNoAck(halHandle->i2cHandle) )
    {
        I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
        I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
    }
    I2C_putData(halHandle->i2cHandle, data);

    while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
    // If a NACK occurred, SCL is held low and STP bit cleared
    if ( I2C_isNoAck(halHandle->i2cHandle) )
    {
        I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
        I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
    }


    while(!I2C_isStopConditionDetected(halHandle->i2cHandle));
} // end of accel_Write() function

The while loops are there as the make sure data is loaded into the output shift register when it is ready and to handle NACKS.

I'd appreciate any help in trying to get this to work. 

Thanks,

Joshua Russell

  • Update: I've updated managed to get output back on the i2C lines. Here is my updated code:

    void accel_Write(HAL_Handle halHandle, uint16_t register_add, uint16_t data ){
    //    I2C_enable(halHandle->i2cHandle);
    //
        while(I2C_isMasterBusy(halHandle->i2cHandle));
        I2C_clearStopConditionDetection(halHandle->i2cHandle);
        while(I2C_isMasterStopBitSet(halHandle->i2cHandle));
    
    
    //    while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
    //    // If a NACK occurred, SCL is held low and STP bit cleared
    //    if ( I2C_isNoAck(halHandle->i2cHandle) )
    //    {
    //        I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
    //        I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
    //    }
        //I2C_disable(halHandle->i2cHandle);
        I2C_MasterControl(halHandle->i2cHandle, I2C_Control_Single_TX, 0, 2);
    
    
        while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
        // If a NACK occurred, SCL is held low and STP bit cleared
        if ( I2C_isNoAck(halHandle->i2cHandle) )
        {
            I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
            I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
            return;
        }
        I2C_putData(halHandle->i2cHandle, register_add);
    
        while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
        // If a NACK occurred, SCL is held low and STP bit cleared
        if ( I2C_isNoAck(halHandle->i2cHandle) )
        {
            I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
            I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
            return;
        }
        I2C_putData(halHandle->i2cHandle, data);
    
        while(!((I2C_getStatus(halHandle->i2cHandle) & (I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_BITS))));
        // If a NACK occurred, SCL is held low and STP bit cleared
        if ( I2C_isNoAck(halHandle->i2cHandle) )
        {
            I2C_setMasterStopBit(halHandle->i2cHandle);  // send STP to end transfer
            I2C_clearNoAckBit(halHandle->i2cHandle);     // clear NACK bit
            return;
        }
    
        I2C_setMasterStopBit(halHandle->i2cHandle);
    
        while(!I2C_isStopConditionDetected(halHandle->i2cHandle));
    } // end of accel_Write() function

    There is a screen shot of my output below. Oddly, most of the time I am getting the result on the left. It is almost correct, but all of the bits seem to be shifted to the right by one. I believe the cause is because of the oddly short start condition hold time. I have no idea how to manipulate that. 

    On the right is what I would like to see. The first "diamond" represents the longer start condition, and the last two represent the "Ack" and the Stop bit. 

    With the code updated as is above, most of the data frames appear as on the left, with the odd frame here and there being correct. 

    If I comment out the top 3 lines of code in the function (the while busy/clearSCD/isStpbitset lines), I manage to get almost the correct output. EXCEPT, there is no Stop bit, and the first two writes sent out appear as is on the left. 

  • Hello Joushua,

    Performing a brief overview of your initialization and write function, I don't see anything that necessarily stands out. Can you confirm that your SYSCLK is running at 90Mhz? This would be to confirm that your I2C module clock is set-up appropriately below:

        // I2CCLK = SYSCLK/(I2CPSC+1)
        // Prescaler - need 7-12 Mhz on module clk bitTimeLow = 10, bitTimeHigh = 5
        I2C_setupClock(obj->i2cHandle, 9, 76, 38);//I2C_PRESCALER, I2C_BITTIMELOW, I2C_BITTIMEHIGH);

    I believe you are correct in seeing that everything is shifted to the right 1 bit in the set of data shown to the left. This seems to be caused by the SCL blip highlighted below, where an extra 0 bit is created:

    Something is causing the SCL line to be brought low for a very short period of time. How often are you seeing this issue? The MCU should not be causing this since that is not a real SCL clock cycle (I.E. doesn't seem to match the clocking characteristics set or seen in other SCL cycles).

    I'd suggest investigating this further, make sure your connections are all secure. Maybe even testing on a different I2C waveform analyzer if possible.

    Hope this helps,

    Kevin

  • Hello Kevin,

    I managed to change the clock register values so they would produce a 50% High/ 50% Low time, and the cycle is at 100kHz, which I checked using my logic analyzer, so I do believe the board is running at 90MHz.

    The SCL issue is very sporadic, and there is no real consistency to it. Sometimes it happens (and sometimes is "fixed") by turning the board off and then on. I've double checked to connections.

    I went on the write a function that could read a single byte over I2C. The signal looked as expected, (Write, Sub_Addr+W, Restart, Sub_Addr+R, Data). Then the Start/Bit shift showed up again with it. BUT the data it was retrieving was still correct. That initially made me think it was an issue with my logic analyzer, but now that I think on it, I could see it being other possible issues as well, such as the slave device not seeing the short lived start condition due to timing requirements. I'll double check with a different logic analyzer and go from there.

    Thanks for the suggestions!
  • Hi Joshua,

    I think that's a good idea. It could be something else that's causing the I2C to become out of sync, but I think this is a good place to start. Your signal analyzer could also be catching something that isn't a full clock pulse and wouldn't  realistically cause the I2C bus to be corrupted.

    100kHz is the maximum I2C standard mode clocking frequency. Some slave devices (that do not support fast mode) will not be able to read/write at frequencies higher than 100kHz and may stretch the clock at times to keep up.

    Please note that our device has a 0.6 us minimum hold time by design to meet (up to) the fast-mode spec.

    Seeing if a slave device is accurately receiving correct data may be worthwhile to see if bit errors are actually occurring in practice.

    Best,

    Kevin