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.

[参考译文] TMS320F28388D:CM I2C 读取错误数据

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1442378/tms320f28388d-cm-i2c-reading-bad-data

器件型号:TMS320F28388D
主题中讨论的其他器件:TMP101C2000WARE

工具与软件:

我正在从 CM 访问 I2C 温度器件(TMP101)。CM 在总线上设置为 I2C 主器件。 它仅配置 I2C 从器件、然后每秒读取一次温度数据。

在查看逻辑分析仪上的流量时、看到的流量与预期完全相同、器件将返回正确的数据。 这表明总线事务是正确的(器件正确 ACK)。 但在 CM 固件中、从 I2CMDR 寄存器读取2个字节的数据时经常会收到重复的值。 我不使用中断或 FIFO 机制、而只是做后台轮询循环。 我注意到最后一个有效值保留在 MDR 寄存器中、因此在错误的时间读取寄存器(或如果它未按预期更新)会导致值重复。

我遵循了 TRM 中记录的流程图。 是否有如何使用这些 API 的示例? MDR 中的数据何时有效且就绪、固件如何指示? C2000Ware 示例区域中唯一不适用的图形。

void i2cTemperaturePoll(uint32_t i2cInstance)
{
    if(I2C_isMasterBusy(TEMPERATURE_I2C_BASE))
    {
        return;
    };

    // Set I2C target address
    // FC: write slave address to I2CMSA
    I2C_setSlaveAddress(TEMPERATURE_I2C_BASE, i2cAddresses[i2cInstance], I2C_MASTER_READ);

    // FC: Check busy (may be omitted in single master system)
    while(I2C_isBusBusy(TEMPERATURE_I2C_BASE));

    // Start transaction
    // FC: write xxx0_1011 to I2CMCS
    I2C_setMasterConfig(TEMPERATURE_I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

    for (int i = 0; i < TEMPERATURE_I2C_DATA_BYTES; i++)
    {
        // FC: read I2CMCS
        while(I2C_isMasterBusy(TEMPERATURE_I2C_BASE));

        // FC: ERROR bit == 0?
        i2cBusStatus[i2cInstance] |= I2C_getMasterErr(TEMPERATURE_I2C_BASE);

        // Grab read first data byte
        // FC: Read data from I2CMDR
        rawData[i] = I2C_getMasterData(TEMPERATURE_I2C_BASE);

        if (i < TEMPERATURE_I2C_DATA_BYTES - 1)
        {
            // Continue transaction and STOP
            // FC: write xxx0_1001 to I2CMCS
            I2C_setMasterConfig(TEMPERATURE_I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
        }
        else
        {
            // FC: last byte
            // FC: write xxx0_1101 to I2CMCS
            I2C_setMasterConfig(TEMPERATURE_I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH_ACK);
        }
    }

    // FC: Check busy
    while(I2C_isMasterBusy(TEMPERATURE_I2C_BASE));

    // FC: ERROR bit == 0?
    i2cBusStatus[i2cInstance] |= I2C_getMasterErr(TEMPERATURE_I2C_BASE);
}

我编辑了 CM I2C API 来定义配置类型 I2C_MASTER_CMD_BURST_RECEIVE_FINE_ACK。 此类型定义为:

    //! BURST RECEIVE FINISH
    I2C_MASTER_CMD_BURST_RECEIVE_FINISH          = 0x00000005U,
    //! BURST RECEIVE FINISH WITH ACK
    I2C_MASTER_CMD_BURST_RECEIVE_FINISH_ACK      = 0x0000000dU,

此配置会确认来自器件的数据。 它并非100%必要、但与预期的总线事务相匹配。

谢谢!

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

    您好、Jay:

    让我明天再给您介绍一下。

    此致、

    Aishwarya.

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

    Jay、

    因美国假期而延迟、我们对此深表歉意。 在轮询数据就绪性时、如果不与 I2C 模块的当前状态同步、则可以读取重复的值。 我建议首先轮询 RRDY 标志、然后检查 MDR 以确保其包含有效数据。 您还可以使用逻辑分析仪来验证 I2C 总线的时序。  

    基于轮询的方法对该代码进行一些调整、但使用中断将提供更可靠的方法来同步 读取、特别是在这些突发事务期间。  

    此致、

    Aishwarya.

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

    RRDY 标志在哪里? 我在 I2C 模块的 CM 实现中看不到。 这一个用于 C2000实现。

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

    Jay、

    没错、您是否真的可以尝试轮询 I2CMRIS 寄存器中的相应标志、直到它被清除? 这些中断是否甚至未按预期设置?

    此致、

    Aishwarya.

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

    谢谢、Aishwarya。 我更改了针对通用中断(I2C_MRI_RIS)的代码轮询、而不仅仅是 C2000Ware I2C_isMasterBusy API。 这种更改看起来功能更好、并且可以读取良好的数据。 下面是事务流程的摘要:

    // Set I2C target address
    I2C_setSlaveAddress(I2C_BASE, i2cAddress, I2C_MASTER_READ);
    while(I2C_isBusBusy(I2C_BASE));
    
    // Start transaction
    I2C_clearMasterInt(I2C_BASE);
    
    
    I2C_setMasterConfig(I2C_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    
    // FC: read I2CMCS
    while(I2C_isMasterBusy(I2C_BASE));
    
    // FC: ERROR bit == 0?
    i2cBusStatus |= I2C_getMasterErr(I2C_BASE);
    
    while(!isI2CDataReady()); // wait for ISR
    
    // Grab read first data byte
    rawData = I2C_getMasterData(I2C_BASE);
    
    ....

    我会做一些更多的测试(问题在发布版本上被夸大了)和更新,如果我遇到任何更多的问题。

    Jay

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

    Jay、

    感谢您的更新。  

    此致、

    Aishwarya.  

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

    到目前为止、它似乎工作正常。 我可能会 更仔细地研究不同的中断标志、但是一般的原始中断状态(RIS)有效。 感谢您的帮助。

    Jay

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

    Jay、

    我将继续、将该线程标记为已解决。 如果出现任何其他内容、您可以启动新主题。

    此致、

    Aishwarya.