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.

[参考译文] TM4C1294NCPDT:I2C 线路被保持、尝试读取 TMP117

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1326906/tm4c1294ncpdt-i2c-lines-held-trying-to-read-tmp117

器件型号:TM4C1294NCPDT
主题中讨论的其他器件:TMP117INA233TM4C1230H6PM

您好!  

在传感器论坛上重新发布、因为它似乎没有获得太多关注。  

(使用 TM4C1294NCPDTI3与 TMP117通信)。

我遇到了 I2C 问题、其中的 i2c 线似乎卡住。 它卡在的状态是 CLK 保持高电平而数据保持低电平。  

在写入配置寄存器(01h)并读回16位响应后、一直发生这种情况。 在我从示波器获取的屏幕截图中、似乎数据值正在浏览、但从主站获取 NACK 和 STOP 条件似乎有问题。 导致该故障的原因是什么、或者如何避免它? 这个问题是非常不一致的。  

需要注意的其他事项是 i2c 总线上的4个 INA233、一个 ADXL355BEZ 加速计以及这个 TMP117温度传感器。  

在所有故障中、温度传感器始终是保持线路的外设。  

黄色表示 CLK

蓝色表示数据

请参阅故障波形:

这是循环早期的成功事务:  

任何想法或建议都将对您有所帮助  

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

    您好!

     不确定您是否有与以下帖子中类似的问题。  

    https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/844446/tpsm846c23evm-806-why-ic2-needs-certain-delay-in-tpsm846c23evm-806-for-every-data-byte-transmission

     我没有看到您的代码片段。 但基本来说、只要代码中有如下语句、请替换为  

    替换代码中任意位置的下面一行。

    while (I2CMasterBusy (I2C1_base)); 

    替换为以下两条线。
    while (! I2CMasterBusy (I2C1_base);//将此行添加到原始行的顶部。
    while (I2CMasterBusy (I2C1_base)); 

     

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

    你好,查尔斯,谢谢你的答复。  我正在和 Shaun 一起解决这个问题。  下面是我们用来读取 TMP117的代码、如上面的示波器屏幕截图所示:

    我们通过 TMP117模块进行以下函数调用:

      I2CReadWord(i2cChannel, SLAVE_ADDRESS, TEMP_RESULT_REG, &tempValue, I2C_MSB_FIRST);

    应调用此 I2C 函数(请注意开始/结束关键部分函数仅禁用/启用中断、因此 不会中断 I2C 事务):

    bool I2CReadWord(enum I2C_CHANNEL channel, uint8_t slaveAddress, uint8_t registerAddress, int16_t* outputWord, enum I2C_BYTE_ORDER byteOrder)
    {
        StartCriticalSection();
    
        // Make sure the bus isn't busy before trying to start the transaction
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Set up the slave address with write transaction
        MAP_I2CMasterSlaveAddrSet(i2cChannelInfo[channel].i2cBase, slaveAddress, false);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Store the command data in I2C data register
        MAP_I2CMasterDataPut(i2cChannelInfo[channel].i2cBase, registerAddress);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Start the I2C transaction
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_SEND_START);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Set the data direction to true since the I2C Master is initiating a read from the slave
        MAP_I2CMasterSlaveAddrSet(i2cChannelInfo[channel].i2cBase, slaveAddress, true);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Start receiving data in burst mode
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_START);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Get the first byte
        *outputWord = (MAP_I2CMasterDataGet(i2cChannelInfo[channel].i2cBase) & 0xFF) << (byteOrder == I2C_LSB_FIRST ? 0 : 8);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Request the second (and final) byte
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Read the second byte of data
        *outputWord |= (MAP_I2CMasterDataGet(i2cChannelInfo[channel].i2cBase) & 0xFF) << (byteOrder == I2C_LSB_FIRST ? 8 : 0);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        EndCriticalSection();
    
        i2cChannelInfo[channel].errorStatus = I2C_OK;
        return true;
    }

    WAIT_ON_I2C_BUS_BUS_BUSY 是一个宏命令:

    #define WAIT_ON_I2C_BUS_BUSY(CHANNEL) if(I2CWaitOnMasterBusy(CHANNEL) == false) { EndCriticalSection(); return false; }
    

    I2CWaitOnMasterBusy 函数如下所示:

    bool I2CWaitOnMasterBusy(enum I2C_CHANNEL channel)
    {
        uint32_t tries = 0;
        while(MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase) && tries < timeoutTries)
        {
            TimeDelayMicroseconds(timeoutWaitUs);
            ++tries;
        }
    
        // Check one last time if the I2C bus is busy
        if(MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase))
        {
            // Get any error status that might exist
            i2cChannelInfo[channel].tivaErrorStatus = MAP_I2CMasterErr(i2cChannelInfo[channel].portBase);
    
            i2cChannelInfo[channel].errorStatus = I2C_BUS_BUSY_TIMEOUT;
            return false;
        }
    
        i2cChannelInfo[channel].errorStatus = I2C_OK;
        return true;
    }

    我担心添加 while (! I2CMasterBusy ();调用 I2CMWaitOnMasterBusy  因为在 总线从未繁忙的情况下,我们将无限期地等待。

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

    您好、Terence:

     在硬件中存在已知竞态条件、当处理器尝试轮询 BUSY 位的状态时、该条件设置得不够早。 这是插入  while (! I2CMasterBusy())之前的  while (I2CMasterBusy())。  请参考 C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl-boostxl-sensub\HUMIDITY_sht21_simple 中有关它们如何使用的示例。 下面是一个片段。 虽然我不确定您的特定问题是否与此已知问题相关、但我想先排除该问题。  

    void
    I2CReadCommand(uint32_t * pui32DataRx)
    {
        //
        // Modify the data direction to true, so that seeing the address will
        // indicate that the I2C Master is initiating a read from the slave.
        //
        MAP_I2CMasterSlaveAddrSet(I2C7_BASE, SHT21_I2C_ADDRESS, true);
    
        //
        // Setup for first read.  Use I2C_MASTER_CMD_BURST_RECEIVE_START
        // to start a burst mode read.  The I2C master continues to own
        // the bus at the end of this transaction.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
    
        //
        // Wait until master module is done transferring.
        // The I2C module has a delay in setting the Busy flag in the register so
        // there needs to be a delay before checking the Busy bit.  The below loops
        // wait until the Busy flag is set, and then wait until it is cleared to
        // indicate that the transaction is complete.  This can take up to 633 CPU
        // cycles @ 100 kbit I2C Baud Rate and 120 MHz System Clock.  Therefore, a
        // while loop is used instead of SysCtlDelay.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
    
        //
        // Read the first byte data from the slave.
        //
        pui32DataRx[0] = MAP_I2CMasterDataGet(I2C7_BASE);
    
        //
        // Setup for the second read.  Use I2C_MASTER_CMD_BURST_RECEIVE_CONT
        // to continue the burst mode read.  The I2C master continues to own
        // the bus at the end of this transaction.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    
        //
        // Wait until master module is done transferring.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
    
        //
        // Read the second byte data from the slave.
        //
        pui32DataRx[1] = MAP_I2CMasterDataGet(I2C7_BASE);
    
        //
        // Setup for the third read.  Use I2C_MASTER_CMD_BURST_RECEIVE_FINISH
        // to terminate the I2C transaction.  At the end of this transaction,
        // the STOP bit will be issued and the I2C bus is returned to the
        // Idle state.
        //
        MAP_I2CMasterControl(I2C7_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    
        //
        // Wait until master module is done transferring.
        //
        while(!MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        while(MAP_I2CMasterBusy(I2C7_BASE))
        {
        }
        
        //
        // Note the third 8-bit data is the checksum byte.  It will be
        // left to the users as an exercise if they want to verify if the
        // checksum is correct.
        pui32DataRx[2] = MAP_I2CMasterDataGet(I2C7_BASE);
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在硬件中存在已知的竞争条件,当处理器尝试轮询忙位的状态时,该条件设置得不够早。 这是插入  while (! I2CMasterBusy())之前的  while (I2CMasterBusy())。  请参考 C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl-boostxl-sensub\HUMIDITY_sht21_simple 中有关它们如何使用的示例。 下面是一个片段。 虽然我不确定您的特定问题是否与此已知问题相关、但我想先排除该问题。  [/报价]

    谢谢、Charles。  我明白你在说什么,但你同意插入 while (! I2CMasterBusy ())如果我们遇到这样的情况,忙位设置得足够早,我们就会面临无限期阻塞的风险,对吗?

    此外、我粘贴的上面的代码现在用于具有各种 I2C 器件(几十个)的多个电路板上、在99.9999%的时间内可以正常工作。  如果 I2CMasterBusy ()在我的 I2CWaitOnMasterBusy ()函数中返回 false ,在对 I2C 事务转换为 true 之前,我相信由于 I2CWaitOnMasterBusy () 完成得太快,我们会更经常地看到不良事务。  没有?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我明白你在说什么,但你同意插入 while (! I2CMasterBusy ())如果我们遇到这样的情况,忙位设置得足够早,我们就会面临无限期阻塞的风险,对吗?[/引号]

    您好、Terence:

     抱歉、在您试用后、我不同意、但确认它不起作用。  

    此外,我粘贴的代码正用于具有各种 I2C 器件的多个电路板(数十个),99.9999%的时间可以正常工作。  如果 I2CMasterBusy ()在我的 I2CWaitOnMasterBusy ()函数中返回 false ,在对 I2C 事务转换为 true 之前,我相信由于 I2CWaitOnMasterBusy () 完成得太快,我们会更经常地看到不良事务。  否?[/报价]

    根据我对应用的理解、在读取两个字节后、I2Cis 应该使 NACK 有效以停止进一步的读取。  我还没有完全知道缺失的 NACK 是否与已知问题有关。 请查看另一篇文章,添加  while (! I2CMasterBusy()解决了缺少字节的 问题。 这就是为什么我想你尝试排除你的问题与有 while (! I2CMasterBusy())或不是。  

    https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/741685/tm4c1294ncpdt-i2c-multiple-data-byte-transfer-bytes-being-skipped

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

    您好、Charles - 是的、没问题、我会尝试的。  一个问题:在代码示例中,您发布的代码仅显示  while (!  在 MAP_I2CMasterControl() 调用之后进行的 I2CMasterBusy()调用。  你同意,这是我应该做的唯一的时间 while (! I2CMasterBusy()呼叫?

    例如, 你是否同意我应该使我的 I2CReadWord()函数看起来像这样(注意 while (! I2CMasterBusy()仅在我的 MAP_I2CMasterControl()调用后进行调用:

    bool I2CReadWord(enum I2C_CHANNEL channel, uint8_t slaveAddress, uint8_t registerAddress, int16_t* outputWord, enum I2C_BYTE_ORDER byteOrder)
    {
        StartCriticalSection();
    
        // Make sure the bus isn't busy before trying to start the transaction
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Set up the slave address with write transaction
        MAP_I2CMasterSlaveAddrSet(i2cChannelInfo[channel].i2cBase, slaveAddress, false);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Store the command data in I2C data register
        MAP_I2CMasterDataPut(i2cChannelInfo[channel].i2cBase, registerAddress);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Start the I2C transaction
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_SEND_START);
        while(!MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Set the data direction to true since the I2C Master is initiating a read from the slave
        MAP_I2CMasterSlaveAddrSet(i2cChannelInfo[channel].i2cBase, slaveAddress, true);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Start receiving data in burst mode
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_START);
        while(!MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Get the first byte
        *outputWord = (MAP_I2CMasterDataGet(i2cChannelInfo[channel].i2cBase) & 0xFF) << (byteOrder == I2C_LSB_FIRST ? 0 : 8);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Request the second (and final) byte
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
        while(!MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Read the second byte of data
        *outputWord |= (MAP_I2CMasterDataGet(i2cChannelInfo[channel].i2cBase) & 0xFF) << (byteOrder == I2C_LSB_FIRST ? 8 : 0);
        WAIT_ON_I2C_BUS_BUSY(channel);
    
        EndCriticalSection();
    
        i2cChannelInfo[channel].errorStatus = I2C_OK;
        return true;
    }
    

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

    您好、Terence:   

     我的示例显示了下面的  while (! Map_I2CMasterBusy (I2C7_BASE ))位于 每次调用 MAP_I2CMasterControl()之后的 while (I2CMasterBusy (I2C7_BASE )。  

    //
    //将数据方向修改为 true,以便查看地址
    //指示 I2C 主器件正在从从器件发起读取。
    //
    MAP_I2CMasterSlaveAddrSet (I2C7_BASE、SHT21_I2C_ADDRESS、TRUE);

    //
    //设置第一次读取。 使用 I2C_MASTER_CMD_BURST_RECEIVE_START
    //开始突发模式读取。 I2C 主设备继续拥有
    //此事务结束时总线。
    //
    MAP_I2CMasterControl (I2C7_BASE、I2C_MASTER_CMD_BURST_RECEIVE_START);

    //
    //等待主模块完成传输。
    // I2C 模块在寄存器中设置 BUSY 标志时有延迟,因此
    //在检查 BUSY 位之前需要有一个延迟。 以下环路
    //等待忙标志被设置,然后等待它被清除
    //表示事务已完成。 这最多可以占用633个 CPU
    //周期@ 100 kbit I2C 波特率和120 MHz 系统时钟。 因此、
    // while 循环被用来代替 SysCtlDelay。
    //
    while (! MAP_I2CMasterBusy (I2C7_BASE)
    {

    while (MAP_I2CMasterBusy (I2C7_BASE)
    {

    //
    //从从器件读取第一个字节的数据。
    //
    Pui32DataRx[0]= MAP_I2CMasterDataGet (I2C7_BASE);

    //
    //设置第二次读取。 使用 I2C_MASTER_CMD_BURST_RECEIVE_CONT
    //继续突发模式读取。 I2C 主设备继续拥有
    //此事务结束时总线。
    //
    MAP_I2CMasterControl (I2C7_BASE、I2C_MASTER_CMD_BURST_RECEIVE_CONT);

    //
    //等待主模块完成传输。
    //
    while (! MAP_I2CMasterBusy (I2C7_BASE)
    {

    while (MAP_I2CMasterBusy (I2C7_BASE)
    {

    //
    //从从器件中读取第二个字节的数据。
    //
    Pui32DataRx[1]= MAP_I2CMasterDataGet (I2C7_BASE);

    //
    //设置第三次读取。 使用 I2C_MASTER_CMD_BURST_RECEIVE_FINISH
    //终止 I2C 事务。 在该交易结束时、
    //将发出停止位,I2C 总线返回到
    //空闲状态。
    //
    MAP_I2CMasterControl (I2C7_BASE、I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

    //
    //等待主模块完成传输。
    //
    while (! MAP_I2CMasterBusy (I2C7_BASE)
    {

    while (MAP_I2CMasterBusy (I2C7_BASE)
    {


    //
    //注意,第三个8位数据是校验和字节。 它将
    //如果用户想要验证是否存在
    //校验和正确。
    Pui32DataRx[2]= MAP_I2CMasterDataGet (I2C7_BASE);

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

    好的,我只是想确认,我不应该使用 while (! I2CMasterBusy ())调用在其他 Tivaware 调用(如 MAP_I2CMasterSlaveAddrSet 和 MAP_I2CMasterDataGet)之后。

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

    你好查尔斯-我添加了  while (! I2CMasterBusy()调用在 建议的 MAP_I2CMasterControl()调用之后,它似乎被卡在其中一个调用上。

    我将使用 XDS200进行调试。  当我中断时、我看到 :


    请注意, 我的 I2CReadWord()函数的末尾已接近我之前发布的。

    还有其他建议吗?

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

    您好、Terence:

     我很好奇您运行的 I2C 速度。 是100k 还是更高?

     我讨厌让你尝试那些不能提供积极结果的事情。 能否请您尝试下面这样简单的代码、并确定它是否起作用。 如果它正在工作、那么您可以逐渐重新添加 WAIT_ON_I2C_BUS_BUS_BUS_BUSY 中当前包含错误检查的其他内容。  

     

    bool I2CReadWord(enum I2C_CHANNEL channel, uint8_t slaveAddress, uint8_t registerAddress, int16_t* outputWord, enum I2C_BYTE_ORDER byteOrder)
    {
        StartCriticalSection();
    
        // Make sure the bus isn't busy before trying to start the transaction
        // WAIT_ON_I2C_BUS_BUSY(channel); // Comment this out for now
    
        // Set up the slave address with write transaction
        MAP_I2CMasterSlaveAddrSet(i2cChannelInfo[channel].i2cBase, slaveAddress, false);
        //WAIT_ON_I2C_BUS_BUSY(channel); // This is not really needed as the above function does not involve the bus
    
        // Store the command data in I2C data register
        MAP_I2CMasterDataPut(i2cChannelInfo[channel].i2cBase, registerAddress);
        // WAIT_ON_I2C_BUS_BUSY(channel); // This is not really needed as the above function does not involve the bus
    
    
        // Start the I2C transaction
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_SEND_START);
        //    while(!MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        //    WAIT_ON_I2C_BUS_BUSY(channel);
        while(MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase)); // For send, just use MAP_I2CMasterBusy, not !MAP_I2CMasterBusy
    
        // Set the data direction to true since the I2C Master is initiating a read from the slave
        MAP_I2CMasterSlaveAddrSet(i2cChannelInfo[channel].i2cBase, slaveAddress, true);
       // WAIT_ON_I2C_BUS_BUSY(channel); // This is not really needed as the above function does not involve the bus
    
        // Start receiving data in burst mode
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_START);
        while(!MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        while(MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        //WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Get the first byte
        *outputWord = (MAP_I2CMasterDataGet(i2cChannelInfo[channel].i2cBase) & 0xFF) << (byteOrder == I2C_LSB_FIRST ? 0 : 8);
        // WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Request the second (and final) byte
        MAP_I2CMasterControl(i2cChannelInfo[channel].i2cBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
        while(!MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        while(MAP_I2CMasterBusy(i2cChannelInfo[channel].i2cBase));
        // WAIT_ON_I2C_BUS_BUSY(channel);
    
        // Read the second byte of data
        *outputWord |= (MAP_I2CMasterDataGet(i2cChannelInfo[channel].i2cBase) & 0xFF) << (byteOrder == I2C_LSB_FIRST ? 8 : 0);
        //WAIT_ON_I2C_BUS_BUSY(channel);
    
        EndCriticalSection();
    
        i2cChannelInfo[channel].errorStatus = I2C_OK;
        return true;
    }
    

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

    大家好、Charles -谢谢回复、我没有机会运行您建议的测试、希望明天能进行、不过是几个快速的数据点:

    • 我们的 I2C 总线在400 KPBS 下运行、
    • 在前面显示的测试结果中、我们在 while (! Map_I2CMasterBusy ()),这是在一个定制板上,同一个板 Shaun 在这个线程的顶部显示了示波器屏幕截图。  然而、昨天、我在 连接至 Adafruit TMP117分线板的 Tiva 开发板上运行同样的代码、但是它 始终没有卡住 (! Map_I2CMasterBusy()调用。  我让它运行超过一个小时、并且它每秒大约查询五次 TMP117。  在我们的定制电路板上执行此测试时、它会 在启动时立即卡在 while 环路中、固件会尝试配置 TMP117。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Terence:

     我建议您测试我之前发送的修改后的代码并在 LaunchPad 上运行。 如果可以正常运行、则在定制板上重新运行。 如果结果不同、则可能表明存在一些板级差异、从而导致定制板上出现问题。  

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

    您好,Charles -我是按照您的建议做的。   在连接了 Adafruit TMP117输出板的 Tiva 开发板上运行时、该代码可以正常工作。

    对于我们的定制电路板、我们有两种不同的设置:一种设置是将电路板安装在整个 系统上(包括其他电路板和电子产品)、另一种设置是 Shaun 桌面上的设置、其中仅包括我们的定制电路板和电源。

    星期五晚些时候,我对整个系统进行了一次测试,代码运行正常。  我不能让它运行很长一段时间。

    在 Shaun 的办公桌上测试同一个代码 时、在进行 TMP117初始化时、I2CReadWord 函数无限挂起。  初始化步骤仅尝试在固件启动时读取器件 ID 寄存器(0x0F)。  以下是 CCS 的屏幕截图、其中显示了代码无限期挂起的位置:

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

    您好、Terence:

     Shaun 桌面上的另一个设置,仅包括我们的定制板和电源。

     如果它在所有三种设置(LaunchPad、完全自定义设置和 Shaun 的桌面设置)上都失败、则诊断起来会更容易一些。 但现在、三个设置中有两个正在工作、这说明 Shaun 的本地设置与其他两个设置之间存在一些差异)。 有几个问题和建议:

     -您是否仅将  Shaun 桌面上的定制板连接到 Adafruit TMP117、而没有其他连接? 您在 Shaun 的桌子旁说过、只有定制电路板和电源。 如果没有从器件(例如 TMp117)连接到电路板、那么主器件如何读取寄存器?

     -定制板是否与 总线上有其他组件(例如 INA233和其他组件)的完整设置类似?

     -你说运行同样的代码,连接到 Adafruid TMP117的 LaunchPad 将工作,但不是 Sharun 的板。 您能在读取 ID 寄存器时展示这两者的波形吗?

     -您的 LaunchPad 设置与 Shaun 的本地设置相比,SCL 和 SDA 总线上的上拉电阻值是多少?

     -您的设置上的任何 I2C 从设备是否能够作为一种等待手段来延展 SCL 时钟? 根据 I2C 协议、如果从器件未准备好响应、它可以将 SCL 保持为低电平作为等待状态。 我只是想知道你是否遇到这样的情况。 没有波形、我真的无法判断。  

     -在你的第一个问题描述中,你说它工作99.999%的时间,但现在它似乎是死在初始化。 我对有何差异感到有点困惑。 我们是讨论不同的设置还是相同的设置?

     -实验,如果你把 I2C 的速度降低到100k 而不是400k 呢?

     -当它卡在 Shaun 的板的523行,你能检查 I2CMCS 状态寄存器吗? 您看到任何标志了吗?

     -对于试验,在第523行,你能替换为一个固定环路吗? 我想知道它是否会产生影响。 例如,替换为:

      表示(I=0;I<1000;I++);  

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

    尊敬的 Charles、谢谢您的回复、我已在下方在线回复了您的每一个问题:

    三个设置中有两个正在运行,这说明 Shaun 的本地设置与其他两个设置之间存在一些差异)。

    是的、但 我们在两种设置中都看到了定制电路板的间歇性成功/故障。  我们未看到 Launchpad 设置有任何问题。  Launchpad 设置将始终正确读取 ID 并获得正确的温度。  今天上午早些时候、我让 Launchpad 设置运行了近45分钟。  它每秒读取 TMP117多次。  没有问题。  

    您是否仅将  Shaun 桌面上的定制电路板连接到 Adafruit TMP117,什么也没有连接? 您在 Shaun 的桌子旁说过、只有定制电路板和电源。 如果没有从器件(例如 TMp117)连接到电路板、那么主器件如何读取寄存器?

    Launchpad 设置是唯一使用 Adafruit TMP117输出板的设置。  定制板上安装了 TMP117。

    是一款自定义电路板,该电路板类似于 在总线上具有其他组件(例如 INA233和其他组件)的完整设置?

    硬件在两个定制板上是相同的。  但是、对于这些最新测试、 我们在 Shaun 桌面的定制电路板上运行的固件、我已禁用了与除 TMP117之外的所有组件的 I2C 通信、以便其与 Launchpad 设置尽可能相同。

    您能在读取 ID 寄存器时显示两者的波形吗?

    当然、以下是 尝试读取 ID 时 Shaun 桌面上定制电路板的波形:

    以下是成功读取 ID 的 Launchpad:

    您的 LaunchPad 设置中 SCL 和 SDA 总线的上拉电阻值与 Shaun 的本地设置相比是什么?

    我已使用跳线将 LaunchPad 直接连接到 Adafruit TMP117。   TMP117分线板的原理图 表明其 上有10K 上拉电阻器、我已经确认了这一点。   我们的定制电路板有1.65K 的上拉电阻。

    您的设置中的任何 I2C 从设备是否能够拉伸 SCL 时钟作为等待手段? 根据 I2C 协议、如果从器件未准备好响应、它可以将 SCL 保持为低电平作为等待状态。 我只是想知道你是否遇到这样的情况。 没有波形、我真的无法判断。  [/报价]

    我知道没有时钟拉伸、我认为使用这些最新的测试是有争议的、因为 固件仅尝试与 TMP117进行通信。

    在您的第一个问题描述中,您说它工作了99.999%的时间,但现在初始化似乎已经失效了。 我对有何差异感到有点困惑。 我们讨论的是不同的设置还是相同的设置?

    不同的设置。  除了我们遇到的定制板之外、我们还有 不同的  定制电路板设计(完全不同的电路板设计、以及每个设计多个电路板)。  这些其他定制电路板都带有 TMP117传感器、并使用 Tiva (TM4C1294NCPDT 或 TM4C1230H6PM) 运行完全相同的固件且工作正常。  很抱歉说99.9999%我应该说100%的时间。

    对于实验,如果将 I2C 速度降低到100千而非400千,该怎么办?

    相同的结果、代码挂起在同一行、但 示波器上的 I2C 流量更少。  也许较低的速度允许在固件在 while 环路上挂起之前传输更少的数据?:

    当 Shaun 的电路板卡在523行时,您能检查 I2CMCS 状态寄存器吗? 您是否看到任何标志?

    是的、I2C_MCS_IDLE 和 I2C_MCS_QCMD 都为高电平。  下面是屏幕截图:

    对于实验、第523行、您是否可以替换为固定环路? 我想知道它是否会产生影响。 例如,替换为:

      表示(I=0;I<1000;I++);  

    [/报价]

    我们在 调试版和发布版中均对此进行了尝试。   它现在当然没有卡在 while 循环上(因为我们将其删除)、但 仍然没有读取 ID。   我们也捕获了这方面的波形。  首先粘贴下面的调试构建波形、然后粘贴发布构建波形。   有趣的是 、版本的第一个事务在显示调试版本的写入时如何显示读取。  我想知道编译器是否会在版本构建中优化 for 循环。

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

    当然、以下是 尝试读取 ID 时 Shaun 桌面上定制电路板的波形:

    [/报价]

    您好、Terence:

     在该范围上限中、似乎你首先写入从器件地址0x48、但你从从器件获取一个 NACK、不是吗? 您知道为什么 TMP117对主设备有利吗? 我不熟悉 TMP117、不知道原因。  

    相同的结果、代码挂起在同一行、但 示波器上的 I2C 流量更少。  也许较低的速度允许在固件在 while 环路上挂起之前传输更少的数据?:

    [/报价]

    在100k 时、您正在从从器件地址0x48读取。 从器件再次发送 NACK 应答。 我认为您需要调查为什么从器件没有使用 ACK 进行响应? 当发送器接收到 NACK 时、它将中止事务并在停止时中止。

    我们在 调试版和发布版中均对此进行了尝试。   它现在当然没有卡在 while 循环上(因为我们将其删除)、但 仍然没有读取 ID。   我们也捕获了这方面的波形。  首先粘贴下面的调试构建波形、然后粘贴发布构建波形。   有趣的是 、版本的第一个事务在显示调试版本的写入时如何显示读取。  我想知道编译器是否会在版本构建中优化 for 循环。

    [/报价]

    在此电容器中、从器件再次以 NACK 进行应答。 我认为编译器不会  针对(i=0;i<1000;i++)进行优化。  

    请比较您的定制电路板、因为到 TMP117的所有输入和输出连接与您的其他有效设计和 LaunchPad。 从我能在示波器电容上看到的信息可以看出、从器件由于某种原因没有响应。 当从器件使用 NACK 进行响应时、这通常意味着它尚未准备就绪。  

    是否可以将 TMP117输出板连接到您的定制板并以某种方式禁用您当前的板载 TMP117芯片?

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

    你好查尔斯-大道歉。   Shaun 桌面上定制电路板上的 TMP117传感器似乎 损坏且无响应。  Shaun 将其替换为新的版本、并且像 Launchpad 和 Adafruit TMP117设置一样、立即开始使用预期的回复进行响应。

    我们将开始重新添加其他传感器。  我将 确保 这些传感器使用 while (! 在适当的情况下,当他们进行读取和写入时,会调用 MAP_I2CMasterBusy()。  手指交叉可解决我们的问题。

    我们会经常向您发帖。  我们非常感谢您为此提供的所有帮助。

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

    您好、Terence:

     根据您在本文中的状态、 https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1336570/tm4c1294ncpdt-odd-i2c-error-occurring 我认为 I2C 问题已解决。 我现在将关闭该主题。 如果您有任何更新、您可以写回此帖子、并且状态将更改为"打开"。  

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

    Charles、这些是单独的问题。 不过、我们可能已经解决了这个问题。 作为参考、问题是加速计器件  ADXL355BEZ 在共享 SDA 总线时出现问题。 根据 ADXL355BEZ 的数据表:

    "ADXL355支持点对点 I2 C 通信。 但是、在共享 SDA 总线时、ADXL355可能阻止与该总线上的其他器件进行通信。 如果在任何时候、即使 ADXL355未被寻址、0x3A 和0x3B 字节(当 ADXL355器件地址被设定为0x1D 时)。 或在 SDA 总线上发送0xA6和0xA7字节(当 ADXL355器件地址设置为0x53)、ADXL355以一个确认位进行响应并下拉 SDA 线。 例如、当读取或写入数据字节(0x3A/0x3B 或0xA6/0xA7)到总线上的另一个传感器时、可能发生此响应。 当 ADXL355下拉 SDA 线时、可能会中断与总线上其他器件的通信。 为了解决这个中断问题、ADXL355必须被连接至一个单独的 SDA 总线、或者当不需要与 ADXL355进行通信时(它通常接地)、CS/SCL 引脚必须切换为高电平。 "

    我目前正在自己的 SDA 线(单独的 I2C 总线)上测试 ADXL355BEZ、似乎已修复了此问题。 感谢您的全力帮助。