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.

[参考译文] LP-MSPM0G3507:I2C 数据传输和接收

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1528861/lp-mspm0g3507-i2c-data-transmission-and-reception

器件型号:LP-MSPM0G3507
Thread 中讨论的其他器件:MSPM0G3507SysConfig

工具/软件:

您好、

我们是否可以将数据从一个 I2C 端口传输到同一控制器内的另一个 I2C 端口?
我要使用的 LaunchPad 是:MSPM0G3507

谢谢你  

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

    尊敬的 Tejal:

    没问题。 您可以将一个 I2C 设置为控制器、将另一个设置为从器件、只需将 SCL 和 SDA 引脚连接在一起。

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

    我是否还需要连接上拉电阻器以进行 I2C 通信? 您能为设置 I2C 通信提供一个简单的示例代码吗?

    谢谢您、
    Tejal

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

    尊敬的 Tejal:

    是的、您可以使用内部上拉电阻器或外部上拉电阻器。

    例如、您可以将 i2c 控制器和目标示例合并到一个项目中以供您应用。 中断示例可用于 i2c 目标。

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

    嗨、Pengfei、

    我尝试合并 I2C 控制器和目标示例、但没有收到目标器件的确认。 我还附加了我在逻辑分析仪上观察到的输出。

    谢谢您、
    Tejal

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

    您合并了哪些示例? 我希望您在目标端使用中断驱动模型。

    您是否更改了两侧的目标 I2C 地址?

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

    是的、我更改了两侧的 I2C 地址、还在目标端使用中断驱动代码、并合并了以下 2 个示例:

    1) i2c_controller_multibyte_fifo_poll 和 2) i2c_target_multibyte_fifo_interrupt

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

    尊敬的 Tejal:

    您为 I2C 目标器件使用的中断示例是正确的。

    您可以检查一些项目:

    • 您是从 I2C 主器件写入地址 0x10、是否将 I2C 目标地址更改为 0x10?
    • 是否上拉了 SCL 和 SDA 引脚?
    • 对于 I2C 目标代码、请确保其完全遵循 SDK 示例、尤其是启用中断和中断处理程序实现。   

    此致、

    Pengfei

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

    您能否发布生成的(合并的)代码? 有时它所需要的是一个拼写错误。

    ------------------------

    对于目标端, main () 的内容应该适合“target_init ()“函数,但以下情况除外:

        DL_SYSCTL_enableSleepOnExit();

    这一点应该删除、因为它对程序具有全局影响。 (它可能会产生您所看到的症状。)

        while (1) {
            __WFI();
        }

    应将其删除。 (我猜你已经做到了。)

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

    感谢您的反馈。 我已根据你的建议对守则作了必要的调整。 我 随附了更新后的代码以供您查看。 您能否检查生成的(合并)代码?  

    #include <ti/driverlib/m0p/dl_interrupt.h>
    #include "ti_msp_dl_config.h"
    
    #define I2C_TX_PACKET_SIZE (8)
    
    #define I2C_RX_PACKET_SIZE (5)
    
    #define I2C_TX_MAX_PACKET_SIZE (16)
    
    #define I2C_RX_MAX_PACKET_SIZE (16)
    
    uint8_t gTxPacket[I2C_TX_PACKET_SIZE] = {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    
    volatile uint8_t gRxPacket[I2C_RX_PACKET_SIZE];
    
    uint32_t gTxLen, gTxCount;
    
    /* Data sent to Controller in response to Read transfer */
    uint8_t gTxPacket1[I2C_TX_MAX_PACKET_SIZE] = {0x00};
    volatile uint8_t gRxPacket1[I2C_RX_MAX_PACKET_SIZE];
    
    uint32_t gRxLen, gRxCount;
    
    
    int main(void)
    {
        SYSCFG_DL_init();
    
        gTxCount = 0;
        gTxLen   = I2C_TX_MAX_PACKET_SIZE;
        DL_I2C_enableInterrupt(I2C_1_INST, DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER);
    
        /* Initialize variables to receive data inside RX ISR */
        gRxCount = 0;
        gRxLen   = I2C_RX_MAX_PACKET_SIZE;
    
    
        DL_I2C_fillControllerTXFIFO(I2C_0_INST, &gTxPacket[0], I2C_TX_PACKET_SIZE);
    
        /* Wait for I2C to be Idle */
        while (!(
            DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE))
            ;
    
        DL_I2C_startControllerTransfer(I2C_0_INST, I2C_1_TARGET_OWN_ADDR,
            DL_I2C_CONTROLLER_DIRECTION_TX, I2C_TX_PACKET_SIZE);
    
        /* Poll until the Controller writes all bytes */
        while (DL_I2C_getControllerStatus(I2C_0_INST) &
               DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
            ;
    
        /* Trap if there was an error */
        if (DL_I2C_getControllerStatus(I2C_0_INST) &
            DL_I2C_CONTROLLER_STATUS_ERROR) {
            /* LED will remain high if there is an error */
            __BKPT(0);
        }
    
        /* Wait for I2C to be Idle */
        while (!(
            DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE))
            ;
    
        /* Add delay between transfers */
        delay_cycles(1000);
    
        DL_I2C_startControllerTransfer(I2C_0_INST, I2C_1_TARGET_OWN_ADDR,
            DL_I2C_CONTROLLER_DIRECTION_RX, I2C_RX_PACKET_SIZE);
    
        for (uint8_t i = 0; i < I2C_RX_PACKET_SIZE; i++) {
            while (DL_I2C_isControllerRXFIFOEmpty(I2C_0_INST));
            gRxPacket[i] = DL_I2C_receiveControllerData(I2C_0_INST);
        }
    
        while (1) {
        }
    }
    
    void I2C_1_INST_IRQHandler(void)
    {
        static bool dataRx = false;
    
        switch (DL_I2C_getPendingInterrupt(I2C_1_INST)) {
            case DL_I2C_IIDX_TARGET_START:
                /* Initialize RX or TX after Start condition is received */
                gTxCount = 0;
                gRxCount = 0;
                dataRx   = false;
                /* Flush TX FIFO to refill it */
                DL_I2C_flushTargetTXFIFO(I2C_1_INST);
                break;
            case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER:
                /* Store received data in buffer */
                dataRx = true;
                while (DL_I2C_isTargetRXFIFOEmpty(I2C_1_INST) != true) {
                    if (gRxCount < gRxLen) {
                        gRxPacket1[gRxCount++] = DL_I2C_receiveTargetData(I2C_1_INST);
                    } else {
                        /* Prevent overflow and just ignore data */
                        DL_I2C_receiveTargetData(I2C_1_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_1_INST, &gTxPacket1[gTxCount], (gTxLen - gTxCount));
                } else {
                    while (DL_I2C_transmitTargetDataCheck(I2C_1_INST, 0x00) != false)
                        ;
                }
                break;
            case DL_I2C_IIDX_TARGET_STOP:
                /* If data was received, echo to TX buffer */
                if (dataRx == true) {
                    for (uint16_t i = 0;
                         (i < gRxCount) && (i < I2C_TX_MAX_PACKET_SIZE); i++) {
                        gTxPacket1[i] = gRxPacket1[i];
                        DL_I2C_flushTargetTXFIFO(I2C_1_INST);
                    }
                    dataRx = false;
                }
                break;
    
            default:
                break;
        }
    }

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

    > DL_I2C_enableInterrupt (I2C_1_INST、DL_I2C_INTERRUPT_TARGET_TXFIFO_TRIGGER);

    之后、我认为您还需要(我猜是 IRQN 名称):

    > NVIC_EnableIRQ (I2C_1_IRQN);//在 NVIC 中启用目标中断

    -----

    但这不会导致 NACK。 我想知道 ti_msp_dl_config.c 中的 I2C_1(目标)设置是否缺少对以下内容的调用:

    > DL_I2C_setTargetOwnAddress (I2C_1_INST、I2C_1_TARGET_OWN_ADDR);

    这是在示例中由 SysConfig 生成的、但也许它在合并中丢失了?

    -----

    更笼统地说、您似乎对两侧使用相同的 Tx/Tx Rx 缓冲区。 也许您已经检查过它是否正常工作、但乍一看似乎很危险。