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.

CC1352R: CC1352 I2c

Part Number: CC1352R
Other Parts Discussed in Thread: TMP116, TMP102, BOOSTXL-BASSENSORS

Hai, 

I am working on CC1352R sensor code. I am reading temperature data using i2c peripheral with callback function.

At the initialize time i open i2c only once and reading temperature value in event for every 5 sec , i am getting temperature value.

But If  i am trying to open i2c and read the temperature value and close the i2c every time in event, i am not getting temperature value because of i2c transfer failed. is there any problem if i open and close i2c in event??

  • Hi Mamatha,

    It would be helpful if you shared code showing how you use it in both cases. As for closing the I2C, is there a reason you want to open / close the driver each time?
  • I am using TMP116 temperature. This temperature sensor is not giving 90% change of temperature with in 5 minutes. It is taking more time to reach 90% of changed temperature. That way i am trying to reinitialize I2c.

    this is working code

    void Temperature_Init(void)
    {
    I2C_init();
    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2cParams.transferMode = I2C_MODE_CALLBACK;
    i2cParams.transferCallbackFxn= Temperature_CallbackFxn;

    i2c = I2C_open(Board_I2C0, &i2cParams);

    if (i2c == NULL)
    {
    ;
    }
    else
    {
    ;
    }
    }

    float Cal_Temperature(void)
    {
    memset(rxBuffer, 0, 2);
    /* Point to the T ambient register and read its 2 bytes */
    txBuffer[0] = TEMPERATURE_REGISTER;
    i2cTransaction.slaveAddress = TMP_SLAVE_ADDRESS;
    i2cTransaction.writeBuf = txBuffer;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf = rxBuffer;
    i2cTransaction.readCount = 2;
    if (I2C_transfer(i2c, &i2cTransaction))
    {
    ;
    }
    else
    {
    Temperature_value = 0.0;
    }
    return Temperature_value;
    }
    void Temperature_CallbackFxn(I2C_Handle handle, I2C_Transaction *transaction, bool transferStatus)
    {
    Temperature_value = 0;
    Temp = 0;
    Temp = rxBuffer[0];
    Temp = Temp<<8;
    Temp = Temp|rxBuffer[1];
    //Because 1 LSB=0.0078125 centi grade
    Temperature_value = Temp*0.0078125;
    }
    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    this is another code

    void Temperature_Init(void)
    {
    I2C_init();
    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2cParams.transferMode = I2C_MODE_CALLBACK;
    i2cParams.transferCallbackFxn= Temperature_CallbackFxn;

    /* Point to the T ambient register and read its 2 bytes */
    txBuffer[0] = TEMPERATURE_REGISTER;
    i2cTransaction.slaveAddress = TMP_SLAVE_ADDRESS;
    i2cTransaction.writeBuf = txBuffer;
    i2cTransaction.writeCount = 1;
    i2cTransaction.readBuf = rxBuffer;
    i2cTransaction.readCount = 2;

    }


    float Cal_Temperature(void)
    {
    i2c = I2C_open(Board_I2C0, &i2cParams);

    if (i2c == NULL)
    {
    ;
    }
    else
    {
    ;
    }

    if (I2C_transfer(i2c, &i2cTransaction))
    {
    ;
    }
    else
    {
    Temperature_value = 0.0;
    }
    I2C_close(i2c);
    return Temperature_value;
    }
  • please respond to my question.

  • I try to add while(1) in tmp007 example to test I2C_open/I2C_close repeatively and don't see any problem when I test it.

    void *mainThread(void *arg0)
    {
        unsigned int    i;
        uint16_t        temperature;
        uint8_t         txBuffer[1];
        uint8_t         rxBuffer[2];
        I2C_Handle      i2c;
        I2C_Params      i2cParams;
        I2C_Transaction i2cTransaction;

        /* Call driver init functions */
        Display_init();
        GPIO_init();
        I2C_init();

        /* Configure the LED pin */
        GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

        /* Open the HOST display for output */
        display = Display_open(Display_Type_UART, NULL);
        if (display == NULL) {
            while (1);
        }

        /* Turn on user LED */
        GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
        Display_printf(display, 0, 0, "Starting the i2ctmp007 example\n");

        /* Create I2C for usage */
        I2C_Params_init(&i2cParams);
        i2cParams.bitRate = I2C_400kHz;
        while(1){
            i2c = I2C_open(Board_I2C_TMP, &i2cParams);
            if (i2c == NULL) {
                Display_printf(display, 0, 0, "Error Initializing I2C\n");
                while (1);
            }
            else {
                Display_printf(display, 0, 0, "I2C Initialized!\n");
            }
        
            /* Point to the T ambient register and read its 2 bytes */
            txBuffer[0] = TMP007_OBJ_TEMP;
            i2cTransaction.slaveAddress = Board_TMP_ADDR;
            i2cTransaction.writeBuf = txBuffer;
            i2cTransaction.writeCount = 1;
            i2cTransaction.readBuf = rxBuffer;
            i2cTransaction.readCount = 2;
        
            /* Take 20 samples and print them out onto the console */
            for (i = 0; i < 20; i++) {
                if (I2C_transfer(i2c, &i2cTransaction)) {
                    /* Extract degrees C from the received data; see TMP102 datasheet */
                    temperature = (rxBuffer[0] << 6) | (rxBuffer[1] >> 2);
        
                    /*
                     * If the MSB is set '1', then we have a 2's complement
                     * negative value which needs to be sign extended
                     */
                    if (rxBuffer[0] & 0x80) {
                        temperature |= 0xF000;
                    }
                   /*
                    * For simplicity, divide the temperature value by 32 to get rid of
                    * the decimal precision; see TI's TMP007 datasheet
                    */
                    temperature /= 32;
        
                    Display_printf(display, 0, 0, "Sample %u: %d (C)\n", i, temperature);
                }
                else {
                    Display_printf(display, 0, 0, "I2C Bus fault\n");
                }
        
                /* Sleep for 1 second */
                sleep(1);
            }
        
            /* Deinitialized I2C */
            I2C_close(i2c);
            Display_printf(display, 0, 0, "I2C closed!\n");
        }
        return (NULL);
    }

  • Hi YiKai Chen,
    If I implement this code in driver example this is working fine. But same code is not working with sub 1GHZ sensor code.

  • Hi Mamatha,

    You did not really explain why you would like to open / close the I2C driver repetitively in the event rather then just opening it once and reusing the handle. As for possible issues with this, it would depend on which SDK version you are running.

    If not doing so already, I would advice you to try to use the latest SDK which would be v2.40 IF you have a revision E device. If you don't have the revision E launchpad, you should use v2.30 as this is the last SDK supporting the older chip revisions.
  • I test this I2C open/close in sensor read event using SDK 2.30 and I can see the problem. Do you know why we fail to do I2C open/close repeatedly in a periodic event?
  • Hi YiKai,

    Are you able to scope the line and check the state of them during the open/close call? The I2C hardware does not have any reset mechanism which means some state can "bleed over" from the open/close run to another if the module is never powered down.

    In these situations, there is a chance that if your bus happens to be in a state which makes the I2C hardware "busy" when closing, this status could get stuck and remain "busy" when you open the driver again. Could you check and see if this is what you are actually seeing (because this would fail the transfer).

    There was initially a bug in the driver that was addressed for the 2.30 SDK that could cause this error during close even if the bus was ok.
    Unfortunately, I think the issue could still be seen if the bus is not in idle state when calling close.
  • How can I use scope to check the state of them during the open/close call?
  • Well, there is a few ways to check this. You could check if any of the lines are low before closing the I2C (use GPIO toggles around it to isolate it).
    You could also break before the open call and see if the I2C registers can be accessed, if they can, you have not powered of that domain yet (could be another driver keeping it alive or you simply not been in standby). If you can access them, you can also check the status register to see if is marked as "busy" or something else.
  • @, I had check I2C SCK/SDA pins with scope and they are kept high when the application calls I2C open and close. Also, I cannot access to I2C registers after application closes I2C and before reopening it next time, which means I2C is close successfully. However, I still see I2C transfer fail... Any new suggestion?

  • Hi M-W
    I want to use two slaves. That way i am trying to open/close the i2c driver repetitively in the event.
  • You don't have to open/close the i2c driver repetitively in the event even you use two I2C slaves. You only need to change I2C address.
  • Hi YiKai Chen,
    I changed address of slave without reopen and close the i2c driver, but it is not working.
  • I suggest you to use I2C protocol analyzer or scope to check if I2C signal is correct first.
  • @YiKai,
    Were you able to step into the transfer call and see for what reason it return failure? Is it due to some initial checks failing or due to an actual transaction error?
  • @M-W, It won't enter the following code because object->mode is I2CCC26XX_ERROR. I do trace why it become I2CCC26XX_ERROR but CCS doesn't show me callstack.

    if (object->mode == I2CCC26XX_IDLE_MODE) {
    DebugP_log1(
    "I2C:(%p) Transfer OK",
    hwAttrs->baseAddr);
    ret = true;
    }
  • Hi YiKai Chen,
    1. Now My two slaves are working fine in i2c blocking mode.
    if i am using i2c blocking mode, is there any problem to RF section(sub1GHZ)???

    2. when i am using i2c call back, RTC is not updating date&time,but i can able to read the date&time.
    why RTC not updating date&time in callback mode??
  • 1. I suppose it shouldn't impact RF section.
    2. I see no reason why RTC is not updating.
  • Hi YiKai,

    I think this is mainly done inside the Hwi function. I wonder if it could be a matter of "early interrupts". Can you put a breakpoint down in the Hwi and see if you end up there following the open call?
  • I couldn’t understand what you mean “put a breakpoint down in the Hwi”. Can you show me how to do this?
  • Hi YiKai,

    What I mean is adding the I2C source code to the project and putting a breakpoint in the beginning of the "I2CCC26XX_hwiFxn" function. You should then see if you are getting a interrupt following I2C_open() or not.
  • Yes, I get a interrupt (I2CCC26XX_ERROR) following I2C_open().
  • Hi YiKay,

    What is the content of the MSTAT register when you enter the interrupt? I don't see any reason for you to receive an interrupt assuming the state is as you say (lines kept high during open/close and the register being "inaccessible" before calling open).

    Could you attach the project you use when testing this so I can look closer at it?
  • I just test it again with the same code and the issue disapears. I suspect the HW connect between my LaunchPad and BOOSTXL-BASSENSORS is not good to cause this issue. I think we can close this issue. Thanks for your help.