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.

[参考译文] MSPM33C321A:在 TX 缓冲器为空时、I2C 数据传输卡在等待中

Guru**** 2756835 points

Other Parts Discussed in Thread: LP-MSPM33C321A

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1608601/mspm33c321a-i2c-data-transfer-stuck-waiting-at-tx-buffer-empty

器件型号: MSPM33C321A

您好的团队、  

我正在使用 LP-MSPM33C321A、能够使计时器正常工作、但在向 I2C 传感器发送数据时出现问题。 以下代码应向传感器发送一个字节寄存器地址和一个字节的数据、但始终会在 Tx 缓冲区为空的情况下一直等待:DL_I2CC_isTXFIFOEmpty (I2C_INST);

 

这可能是什么导致它坚持在这里? 使用前是否需要配置 FIFO 大小/阈值? 我正在使用的示例具有 64 字节的 FIFO 大小(可能对于 2 字节的数据传输来说太大?)

 

I2C 总线通过 10K 电阻器拉至 3.3V、并且我可以测量总线上的电压是正确的。  

 

void Sensor_write_reg(uint8_t reg, uint8_t data)

{

    transmitData[0] = reg;  // Reg address

    transmitData[1] = data;  // Data to the Reg

 

    /*

     * Fill FIFO with data.

     */

    Size = DL_I2CC_fillTXFIFO(I2C_INST, &transmitData[0], CommandSize);

 

    // Start transfer

    DL_I2CC_startTransfer(I2C_INST,I2C_TARGET_ADDRESS,DL_I2CC_DIRECTION_TX, CommandSize);

 

    // Wait for TX FIFO ready     but the code waits here forever.......... 

     while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && DL_I2CC_getStatus(I2C_INST) != DL_I2CC_STATUS_ERROR) {

     };

 

     /* Wait for I2C to be Idle */

    while (!(DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_IDLE))

        ;

     /* Add delay between transfers */

    delay_cycles(1000);

 

}

 

此致、
Luke

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

    >    while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && DL_I2CC_getStatus(I2C_INST) != DL_I2CC_STATUS_ERROR) {

    getStatus() 返回所有的 SR、并且 STATUS_ERROR 只是其中的一个位 (UNICOMMI2CC_SR_ERR_MASK)。 请尝试:

    >    while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0 && (DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_ERROR) == 0) {

    Supposing that is what you encountered, I suspect you got a NACK from the target device, which is a different problem.

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

    您好 Bruce、  

    感谢您的答复!  当我只检查 FIFO 是否为空时、就会卡住在那里、因为 FIFO 永远不会通过以下代码变空:

    while (DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0);

    而无需检查任何错误。

    此致、

    Luke

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

    如果你得到一个 NACK, TX FIFO 不会空——你必须识别事件并自己清空它。 [参考 TRM (SLAU962) 第 23.2.3.4 节(最后一段)]。 通过我建议的更改、您至少能够知道发生了什么。

    假设您收到了 NACK:(1) 检查 I2C 地址 (2) 检查器件 (Vcc) 是否通电 (3) 检查接线 (4) 如果您有示波器、这可能是深入探究的好时机。

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

    嗨、Bruce、

    我将代码更改为您的建议:while (DL_I2CC_isTXFIFOEmpty (I2C_INST)== 0 &&(DL_I2CC_getStatus (I2C_INST)& DL_I2CC_STATUS_ERROR)== 0){

    现在我可以传递 I2C 写入命令、示波器显示了总线上的时钟和数据。 遗憾的是、在我执行旧的工作代码之后、传感器仍然无法工作(打开)。 我们已经对硬件进行了更改、以便适应 3V 总线、而不是旧的 5V 总线。  

    非常奇怪的它工作了一段时间,并在重新编程的电路板后,它不再发送时钟和数据了。

    此致、

    Luke

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

    如果是目标(出于任何原因)挂起总线、那么重置或重新编程控制器端不一定会清除它。 可能也应该对目标端进行下电上电。

    您能告诉我们目标是什么吗?  

    另外、 CommandSize 的值是多少? 如果大于 8、可能需要更多代码来重新填充 TX FIFO。

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

    我在两侧都重新接通电源、但没有解决问题。 传感器(目标侧)是一个使用 MAX86916 的自模传感器。

    我很好奇为什么传输可以工作(至少我可以看到时钟和数据线活动,并能看到缓冲区很长时间清空,然后突然停止)。 CommandSize 的值仅设置为 2。 以下是当前代码。 我不再在总线上看到时钟或数据。

    /* I2C Target address */

    #define I2C_TARGET_ADDRESS (0x57)

    #define CommandSize 2

    uint8_t gTxCount = 0;

    int Timer0IsInt = 0, NumOfTimerInt = 0, Alt = 0;

    int Count = 0, Size = 0;;

     

    uint8_t transmitData[2] ={};

     

    void Sensor_write_reg(uint8_t reg, uint8_t data, uint8_t uch_sensor)

    {

        transmitData[0] = reg;  // Reg address

        transmitData[1] = data;  // Data to the Reg

       

        if(uch_sensor == I2C0)

        {

     

            //Fill FIFO with data.

            Size = DL_I2CC_fillTXFIFO(I2C_INST, &transmitData[0], CommandSize);

     

            // Start transfer

            DL_I2CC_startTransfer(I2C_INST,I2C_TARGET_ADDRESS,DL_I2CC_DIRECTION_TX, CommandSize);

     

            // Wait for TX FIFO ready

            while(DL_I2CC_isTXFIFOEmpty(I2C_INST) == 0&&(DL_I2CC_getStatus(I2C_INST)&DL_I2CC_STATUS_ERROR) == 0) ;

     

            /* Wait for I2C to be Idle */

            while (!(DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_IDLE));

     

        } else //The other sensor

        {

            //Fill FIFO with data.

     

            Size = DL_I2CC_fillTXFIFO(I2C_0_INST, &transmitData[0], CommandSize);

     

            // Start transfer

            DL_I2CC_startTransfer(I2C_0_INST,I2C_TARGET_ADDRESS,DL_I2CC_DIRECTION_TX, CommandSize);

     

            // Wait for TX FIFO ready

            while(DL_I2CC_isTXFIFOEmpty(I2C_0_INST) == 0 && (DL_I2CC_getStatus(I2C_INST) & DL_I2CC_STATUS_ERROR) == 0) ;

       

            /* Wait for I2C to be Idle */

            while (!(DL_I2CC_getStatus(I2C_0_INST) & DL_I2CC_STATUS_IDLE));

        }    

        /* Add delay between transfers */

        delay_cycles(1000);

    }

    此致、

    Luke

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

    事务停止时:(1)[SDA/SCL]引脚的状态是什么? (2) 如果你暂停你的程序,它在哪里执行?

    我尝试了 2 个实验:

    a) 我窃取了 i2c_controller_rw_multibyte_poll 的副本、以在 5 分钟左右的时间内重复调用此函数。 我本来以为是 NACK、但我得到了、但它并没有挂起。

    b) 我将程序从 (a) 更改为与 Adafruit MPR121 分线板(地址 0x5A)通话、将 0xAA 重复写入寄存器 0x5B【去抖】约 5 分钟。 所有事务都成功、我没有看到任何挂起。

    我想知道您发布的代码之外是否有其他内容。

    [编辑:另外,请使用插入->代码;这使得阅读和复制/粘贴更加容易。]

    【编辑:轻微澄清。】

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

    您好 Bruce、  

    您是否能够分享您拥有的工作测试代码、以便我查看并比较我们的代码中出现的问题?

    此致、

    Luke

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

    以下是我正在处理的内容。 它在 PA10/11 上仅使用一个 I2C(因为我的 LaunchPad 上未安装 PA0/1 上拉电阻)。

    e2e.ti.com/.../x_2D00_i2c_5F00_controller_5F00_rw_5F00_multibyte_5F00_fifo_5F00_poll_5F00_LP_5F00_MSPM33C321A.zip