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.

[参考译文] MSPM0G1505:无法从 I2Cn`t 最新的 TX 数据

Guru**** 2392095 points
Other Parts Discussed in Thread: MSPM0G1505

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1481364/mspm0g1505-can-t-get-the-latest-tx-data-from-i2c

器件型号:MSPM0G1505

工具与软件:

尊敬的 TI 团队:

我想通过 I2C 从 MSPM0G1505获取一些信息。

现在、我可以成功从 MSPM0G1505获得响应、但似乎我得到了最后一次 TX 缓冲区。

例如、我发送0x1、我想接收0x1、但我第一次接收0x00、除非我再次发送0x1、然后我接收到0x1。

然后、我发送0x2、我希望第一次接收0x2 0x1、但我仍然接收到0x1、除非我再次发送它。

发送0x1 0x2时也会发生同样的问题、我似乎总是从最后一次获得 TX 缓冲区。 我想知道为什么以及如何优化我的代码。

我已经上传了日志和代码的一些关键部分。 如果有任何问题、可以帮助您进行审查吗?

void I2C_0_INST_IRQHandler(void)
{
    static bool dataRx = false;

    switch (DL_I2C_getPendingInterrupt(I2C_0_INST))
    {
        case DL_I2C_IIDX_TARGET_START:
            // Initialize RX or TX after Start condition is received
            //gTxCount = 0;
            gRxCount = 0;
            // Flush TX FIFO to refill it
            //DL_I2C_flushTargetTXFIFO(I2C_0_INST);
            break;
        case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER:
            // Store received data in buffer
            dataRx = true;
            while (DL_I2C_isTargetRXFIFOEmpty(I2C_0_INST) != true)
            {
                uint8_t receivedData = DL_I2C_receiveTargetData(I2C_0_INST);
                if (gRxCount < gRxLen)
                {
                    gRxPacket[gRxCount++] = receivedData;
                }
                else
                {
                    DL_I2C_receiveTargetData(I2C_0_INST);
                }

            }
            break;
        case DL_I2C_IIDX_TARGET_TXFIFO_TRIGGER:
            //  Fill TX FIFO if there are more bytes to send
            if (gTxCount < gTxLen)
            {
                //gTxCount += DL_I2C_fillTargetTXFIFO(I2C_0_INST, gTxPacket, gTxLen);
                gTxCount += DL_I2C_fillTargetTXFIFO(I2C_0_INST, &gTxPacket[gTxCount], (gTxLen - gTxCount));
            }
            else
            {
                //
                // Fill FIFO with 0x00 if more data is requested than
                // expected gTxLen
                //
                while (DL_I2C_transmitTargetDataCheck(I2C_0_INST, 0x00) != false);
            }
            break;
        case DL_I2C_IIDX_TARGET_STOP:
            //  If data was received, echo to TX buffer
            if (dataRx == true)
            {
                if(gRxPacket[0] == 0x1)
                {
                    if(gRxPacket[1] == 0x2)
                    {
                        gTxPacket[0] = 0xf;
                        gTxPacket[1] = 0x4;
                        gTxLen = 2;
                        DL_I2C_flushTargetTXFIFO(I2C_0_INST);
                    }
                    else 
                    {
                        gTxPacket[0] = 0x1;
                        gTxLen = 1;
                        DL_I2C_flushTargetTXFIFO(I2C_0_INST);
                    }
                }


                if(gRxPacket[0] == 0x2)
                {
                    gTxPacket[0] = 0x2;
                    gTxPacket[1] = 0x1;
                    gTxLen = 2;
                    DL_I2C_flushTargetTXFIFO(I2C_0_INST);
                }

                if(gRxPacket[0] == 0x3)
                {
                    uint16_t temp_vgs1 = 500; //500 = -3.87V
                    DL_Timer_setCaptureCompareValue(PWM_1_INST, temp_vgs1, GPIO_PWM_1_C1_IDX);    //PWM_Vgs_PA0(10)  Vgs-PA0
                    DL_Timer_setCaptureCompareValue(PWM_2_INST, temp_vgs1, GPIO_PWM_2_C0_IDX);    //PWM_Vgs_PA1(11)  Vgs-PA1
                    DL_Timer_setCaptureCompareValue(PWM_0_INST, temp_vgs1, GPIO_PWM_0_C3_IDX);    //PWM_Vgs_PA2(14)  Vgs-PA2
                    DL_Timer_setCaptureCompareValue(PWM_0_INST, temp_vgs1, GPIO_PWM_0_C1_IDX);
                    gTxPacket[0] = 0x6;
                    gTxLen = 1;
                }

                //DL_I2C_flushTargetTXFIFO(I2C_0_INST);
                gTxCount = 0;
                dataRx = false;
                //cleanRxPacket();
            }
            //  Toggle LED to indicate successful RX or TX
            //  DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
            break;
        case DL_I2C_IIDX_TARGET_RX_DONE:
            //  Not used for this example
        case DL_I2C_IIDX_TARGET_RXFIFO_FULL:
            //  Not used for this example
        case DL_I2C_IIDX_TARGET_GENERAL_CALL:
            //  Not used for this example
        case DL_I2C_IIDX_TARGET_EVENT1_DMA_DONE:
            //  Not used for this example
        case DL_I2C_IIDX_TARGET_EVENT2_DMA_DONE:
            //  Not used for this example
        default:
            break;
    }

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

    一些附加信息

    如代码所示、当我第一次将0x3发送到 MSPM0G1505时、虽然我得到的是最后一次缓冲区[错误的缓冲区、而不是0x6]、但我观察到电压实际上发生了变化。

    我想这可能只是 TX 缓冲区由于某种未知原因而出现延迟。

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

    尊敬的苗老师:
    您要将哪些引脚用于此代码实现? 您是否使用了任何上拉电阻器? 您使用的电阻器值是多少? 我建议将当前 CCS 版本更新/重新安装到最新版本(CCS 20.0.2)和最新 MSPM0 SDKSysConfig。 然后、尝试任何 I2C TX 示例、并查看是否发生了相同的行为。

    此致、

    Diego Abad

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

    这个逻辑似乎要求写入和读取之间有一个停止位、以使缓冲区旋转。 当我阅读 i2ctransfer(8) 手册页时、命令行上的所有"消息"都在一个"传输"(事务)中发送、它在消息之间使用重复启动(无 Stop-s)。

    是否有方法可以将"停止"逻辑安装到"启动"案例中? 或者、尝试在每次 i2ctransfer 运行时发送一条消息。

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

    Bruce、您好!

    感谢您提供的想法。 我使用 i2cget/set 来单独进行写入和写入、看起来是有效的。 我将编写另一个应用、以使用内部停止来执行写入和读取。

    但我注意到 TXFIFO 缓冲区在最后一次发送后没有被清除。  

    `s 读取我得到的是0x0000、因为 TXFIFO 中没有数据、所以这没问题

    `s 次读取、我得到0x040f、因为我将0x01 0x02写入 RX、所以它应该也没有问题。

    但是对于第三次读取、我仍然得到0x040f、似乎 TXFIFO 被`t 成功清除。

    我认为这应该像是一个队列、但 DL_I2C_flushTargetTXFIFO 函数似乎未成功清除 TXFIFO。 您对此问题有任何意见吗?

    非常感谢

    Mervyn

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

    一些更新

    n`t 这个问题,我试图在我的代码中添加 bow case 代码部分,它似乎无法解决这个问题。 我仍在接收上一次 TXFIFO 数据

            case DL_I2C_IIDX_TARGET_TX_DONE:
                DL_I2C_flushTargetTXFIFO(I2C_0_INST);
                break;

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

    尊敬的 miao、
    您是否可以尝试向代码中添加 while (DL_I2C_isTargetTXFIFOEMpty ())? 这将使其停止、直到 TX FIFO 中的所有内容都为空。

    此致、

    Diego Abad

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

    虽然并未明确表示、但 i2cget (8)似乎 设计为读取"寄存器"、这意味着它执行以下序列:(a)写入一个字节(b)重复启动[无停止](c)读取一个{字节或字}(d)停止。

    这是您之前问题的变体。 由于 Stop 只在读取后发生、下一个 i2cget 会重复0x01请求、并且0x02仍留在 gRxPacket 中、因此它返回相同的结果-它不会留在 FIFO 中、您的代码会将其再次放入该 FIFO 中。

    为了确保您知道您发送/接收的内容、我建议您返回 i2ctransfer 并将自己限制为每个"转接"一条"消息"。 [我之所以使用引号、是因为这不是 I2C 规范中使用的术语。]

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

    我认为您还不需要此功能、但由于您关心 Tx FIFO、我建议您读取 TRM Sec 20.2.0.3.12.1、它描述了"过时数据"功能。

    简而言之:在发生某些事件(启动、停止、提到超时)时、Tx FIFO 中的任何数据都标记为"过时"。 您可以启用一项功能、以防止(自动)发送此数据、并提供已发生这种情况的指示。 这样、您就可以在写入要发送的数据之前清空过时数据的 Tx FIFO。  

    现在、您的目标仅提供控制器需要的数据、因此(我认为)您永远不会过度填充 Tx FIFO、但 您可能会牢记这一点、以供将来使用。

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

    Bruce、您好!

    我编写了一个简单的 C 应用程序、用于通过 I2C 进行写入和读取。 似乎分离运算确实可行、并且我每次都可以读取所需的值。

    关于"过时"TXFIFO 数据、我认为在我的方案中不需要此功能。

    不过、出于工程师的精神、我希望能够解决这个问题。 我尚未找到与 MSPM0G1505对应的数字媒体处理器。 我可以参考其他系列吗?

    如果您能为我提供相应的链接、我将不胜感激。  

        if (write(i2c_bus_address, write_buffer, write_length) != write_length)
        {
            perror("Failed to write to the i2c bus");
            close(i2c_bus_address);
            return 1;
        }
    
    
        if (read(i2c_bus_address, read_buffer, read_length) != read_length)
        {
            perror("Failed to read from the i2c bus");
            close(i2c_bus_address);
            return 1;
        }
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如果您认为数字媒体处理器是指 TMS320DM6系列、那么我对它们了解不多。  

    [* Cue TI Sales Department*]