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.

[参考译文] CC2340R5:如何从 I2C 错误中恢复

Guru**** 2650825 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1568239/cc2340r5-how-to-recover-from-an-i2c-error

器件型号:CC2340R5


工具/软件:

你好。 我叫 Mori、

我遇到了 I2C 错误、并尝试执行以下步骤来恢复、但在步骤 ⑩ 中无法进行通信。
复位 CPU 允许 I2C 通信恢复。
但是、我认为当发生 I2C 错误时、I2C_CLOSE→I2C_OPEN 足以作为恢复方法
还有其他问题吗?
感谢您的答复。

① I2C_TRANSFER
② I2C 误差
③ I2C_CLOSE
④ GPIO_resetconfig (SCL)
⑤ GPIO_resetconfig (SDA)
睡眠 ⑥ μ s
I ² C ⑦
⑧ I2C_OPEN
⑩ I2C_TRANSFER

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    抱歉。
    我忘了提到这个。
    我在唤醒后执行了 GPIO_setConfig。
    I2C 通信在步骤 11 中失败。

    ① I2C_TRANSFER
    ② I2C 误差
    ③ I2C_CLOSE
    ④ GPIO_resetconfig (SCL)
    ⑤ GPIO_resetconfig (SDA)
    睡眠 ⑥ μ s
    I ² C ⑦
    ⑧ GPIO_setConfig (SCL)
    ⑨ GPIO_setConfig (SDA)
    ⑩ I2C_OPEN
    ⑪ I2C_TRANSFER

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Mori.OQ

    我希望您做得好。 我创建了一个与您在上面提供的代码类似的代码(减去 GPIO_RESET/setConfig);但是、我的代码显示的行为与您在上面介绍的代码不同(*因为 I2C 仍然有效)。  

    #include <ti/drivers/I2C.h>
    // Define name for an index of an I2C bus
    #define SENSORS 0
    // Define the target address of device on the SENSORS bus
    #define OPT_ADDR 0x47
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        uint8_t writeBuffer[3];
        uint8_t readBuffer[3];
        // One-time init of I2C driver
        I2C_init();
        // initialize optional I2C bus parameters
        I2C_Params params;
        I2C_Params_init(&params);
        params.bitRate = I2C_400kHz;
        // Open I2C bus for usage
        I2C_Handle i2cHandle = I2C_open(SENSORS, &params);
        // Initialize target address of transaction
        I2C_Transaction transaction = {0};
        transaction.targetAddress = OPT_ADDR;
        // Read from I2C target device
        transaction.readBuf = readBuffer;
        transaction.readCount = sizeof(readBuffer);
        transaction.writeCount = 0;
        I2C_transfer(i2cHandle, &transaction);
        // Write to I2C target device
        transaction.writeBuf = writeBuffer;
        transaction.writeCount = sizeof(writeBuffer);
        transaction.readCount = 0;
        I2C_transferTimeout(i2cHandle, &transaction, 5000);
        // Close I2C
        I2C_close(i2cHandle);
        sleep(1);
        I2C_open(SENSORS, &params);
        // Read from I2C target device
        transaction.readBuf = readBuffer;
        transaction.readCount = sizeof(readBuffer);
        transaction.writeCount = 0;
        I2C_transfer(i2cHandle, &transaction);
        // Write to I2C target device
        transaction.writeBuf = writeBuffer;
        transaction.writeCount = sizeof(writeBuffer);
        transaction.readCount = 0;
        I2C_transferTimeout(i2cHandle, &transaction, 5000);
        // Close I2C
        I2C_close(i2cHandle);
        return 0;
    }

    谢谢、
    Alex F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。
    您是否实现了“② I2C 错误“?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Mori.OQ、

    看起来我的代码目前没有在步骤 2 中执行相同的错误、感谢您指出这一点。 您能否在步骤 11 读取 i2c 事务的状态? (即 transaction.status =#)  

    以及中的 SDK 版本。

    谢谢、
    Alex F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。
    Transaction.status 为–5 (I2C_STATUS_ADDR_NACK)。
    SDK 版本为 8.40.00.61。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    其他信息:
    我在 CC2345R5 的引脚 38 (PA5/SCL) 上放置了一个金属物体以导致 I2C 错误。
    我在错误发生后立即移除金属物体。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Mori.OQ

    感谢您提供的额外详细信息、查看您提供的状态可以看到传输失败(地址未确认)、您的另一端是否有子器件运行另一个 I2C 工程? 我还需要在 8.40 SDK 上重新运行代码、因为我的结果来自 9.12 SDK。  

    谢谢、
    Alex F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。
    我正在使用 I2C 与 LCD 驱动程序通信。
    但是、我已经确定从器件(LCD 驱动器)没有问题。
    我发现、即使在 I2C 异常后调用 I2C_OPEN、也无法进行通信、因为 CFE 位无法设置为 1。
    I2CC_Params 将之前由 I2C_Params_init 获得的数据传递到 I2C_OPEN。
    如果您能回答为什么无法设置 CFE 位、我将不胜感激。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Mori.OQ、

    我相信我已经复制了您的问题、将 SCL 引脚接地(就像您预先形成的那样)、我会看到器件在 I2C_TRANSFER 时卡住;在驱动器中看到导致该问题的特定线路是:

    /*等待已准备好的传输完成*/
    if (SemaphoreP_pend (&(object->transferComplete)、timeout)== SemaphoreP_timeout)

    位于 I2C.c 文件中。 看起来像、由于我们将 I2C SCL 引脚接地、器件在传输完成时“始终“挂起(只要该引脚接地,就永远不会这样做)。 我看到、一旦移除接地 SCL 引脚、代码就会恢复、因为传输现在可以完成。

    void *mainThread(void *arg0)
    {
        uint8_t writeBuffer[3];
        uint8_t readBuffer[3];
        // One-time init of I2C driver
        I2C_init();
        while(1)
        {
        // initialize optional I2C bus parameters
        I2C_Params params;
        I2C_Params_init(&params);
        params.bitRate = I2C_400kHz;
        // Open I2C bus for usage
        I2C_Handle i2cHandle = I2C_open(SENSORS, &params);
        // Initialize target address of transaction
        I2C_Transaction transaction = {0};
        transaction.targetAddress = OPT_ADDR;
        // Read from I2C target device
        transaction.readBuf = readBuffer;
        transaction.readCount = sizeof(readBuffer);
        transaction.writeCount = 0;
        I2C_transfer(i2cHandle, &transaction);
        // Write to I2C target device
        transaction.writeBuf = writeBuffer;
        transaction.writeCount = sizeof(writeBuffer);
        transaction.readCount = 0;
        I2C_transferTimeout(i2cHandle, &transaction, 5000);
        // Close I2C
        I2C_close(i2cHandle);
        sleep(1);
        I2C_open(SENSORS, &params);
        // Read from I2C target device
        transaction.readBuf = readBuffer;
        transaction.readCount = sizeof(readBuffer);
        transaction.writeCount = 0;
        I2C_transfer(i2cHandle, &transaction);
        // Write to I2C target device
        transaction.writeBuf = writeBuffer;
        transaction.writeCount = sizeof(writeBuffer);
        transaction.readCount = 0;
        I2C_transferTimeout(i2cHandle, &transaction, 5000);
        // Close I2C
        I2C_close(i2cHandle);
        GPIO_toggle(14);
        }
        return 0;
    }

    谢谢、
    Alex F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。
    因此无法设置 CFE、因为转移未完成。
    软件复位是否是恢复的唯一方法?
    如果有任何其他方法、请告诉我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    抱歉。
    我没读过你的答案
    如您所说、当我移除接地时、I2C 传输完成、
    但即使在经历 I2C_CLOSE→I2C_Init→I2C_OPEN 后、我也无法设置 CFE。 这可能与错误无关、但我想知道您认为什么可能是无法设置 CFE 的原因。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我对缺乏信息深表歉意。
    在本例中、我按顺序处理了 I2C_OPEN、I2C_TRANSFER 和 I2C_CLOSE、
    然后再次执行 I2C_CLOSE。
    这似乎导致在下一个 I2C_OPEN 时 CFE 未设置为 1。
    这是规格问题吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Mori.OQ、

    软件重置是恢复的唯一方法吗?

    如果我们不修改驱动程序代码、软件复位将是当前恢复的唯一方法。  

    这似乎导致下一个 I2C_open 时 CFE 未设置为 1。
    [/报价]

    只是在此处进行澄清、以便我可以尝试复制、在这种情况下、您最初确实将 I2C 接地以使器件卡住、然后移除接地引脚、然后代码 I2C_OPEN、I2C_TRANSFER 和 I2C_CLOSE 正确无误?  

    谢谢、
    Alex F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复。
    我想我没有正确执行。
    我在步骤 ③ 中额外执行了一次 I2C_CLOSE。
    因此、CFE 在步骤 ④ 中没有变为 1。

    ① I2C 误差
    ② I2C_CLOSE
    ③ I2C_CLOSE
    ④ I2C_OPEN
    ⑤ I2C_TRANSFER

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Mori.OQ、

    您可以在第一个 I2C_CLOSE 之后添加另一行代码 、检查 I2C 是否真的关闭(检查 i2cHandle)、如果没有卡在 while 循环中或其他错误情况。  

    谢谢、
    Alex F