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.

[参考译文] MSP430FR2155:I2C 从机中断:每次读取多个 TX 中断

Guru**** 2512495 points
Other Parts Discussed in Thread: MSP430FR2155

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1059840/msp430fr2155-i2c-slave-interrupts-multiple-tx-interrupts-per-single-read

器件型号:MSP430FR2155

您好!

我使用 MSP430FR2155为我的应用实现一些基本的 I2C 读取/写入功能。 MSP430配置为从器件。 我的设置由 Aardvark I2C 器件组成、该器件配置为主机、可从 MSP430读取数据。 我看到的问题是、当主器件在 MSP430侧执行单字节读取操作时、我会接收两个 TX 中断。 我希望主器件执行的每次读取都有一个中断。 当主器件读取一个字节时、我观察到以下中断:

START、TX0、STOP、TX0、9_BIT

如果主器件要执行4字节读取、则会发生以下中断:

START、TX0、TX0、TX0、TX0、 STOP、TX0、9

因此、似乎在停止后会产生一个额外的 TX0中断。 了解此主题的人能否指出初始中断与停止后发生的中断之间的区别? 感谢您将任何线索发送至我可以获取信息的位置(代码、文档等) 谢谢。

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

    您好、Minh、

    是否清除 TX0标志? 这个测试是否在我们的示例代码中进行?

    https://dev.ti.com/tirex/explore/node?node=AGr34Hr5Qoei3oHkYRm5.A__IOGqZri__LATEST

    谢谢!

    此致

    Johnson

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

    尊敬的 Johnson:

    感谢您回答我的问题。 我确实清除了中断例程中的 TX0标志。 我将在本帖子的末尾发布我的代码的要点。 但基本上、主器件发送一个特定的命令供 MSP430执行。 MSP430运行请求的命令、然后将4字节响应存储到数组  gLastCommandStatus 中。 主器件可以通过一次读取一个字节或4字节块来读回这4个字节。 我使用 gLastCommandIndex 跟踪接下来要发送的字节。 当主器件尝试读取超过该4个字节时、返回无效字节。

    在 TX0中断中观察到的 START、TX0、STOP、TX0、9_BIT 行为下、我选择将其视为无效读取、这样就可以正常工作了。 但我知道第二个 TX0中断可以在停止中断之前到达(我已经将 Raspbery Pi 用作主器件);这会使逻辑混乱、导致每个主器件读取跳过一个状态字节。

    我没有第二个 MSP430来尝试您指出的示例、因此主器件必须依赖另一个源(Raspberry PI 或 Aardvark)。 但是、如果发生这种情况、我是否希望每次从主器件 MSP430读取时都只有一个 TX0中断?

    设置 I2C 端口:

    EUSCI_B_I2C_initSlaveParam param = {0};
    param.slaveAddress = MSP430_SLAVE_ADDRESS;
    param.slaveAddressOffset = EUSCI_B_I2C_OWN_ADDRESS_OFFSET0;
    param.slaveOwnAddressEnable = EUSCI_B_I2C_OWN_ADDRESS_ENABLE;
    EUSCI_B_I2C_initSlave(EUSCI_B1_BASE, &param);

    EUSCI_B_I2C_enable (EUSCI_B1_BASE);
    EUSCI_B_I2C_clearInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 +
                                     EUSCI_B_I2C_TRANSMIT_INTERRUPT0 +
                                     EUSCI_B_I2C_BIT9_POSITION_INTERRUPT +
                                     EUSCI_B_I2C_START_INTERRUPT +
                                     EUSCI_B_I2C_STOP_INTERRUPT);
    EUSCI_B_I2C_enableInterrupt(EUSCI_B1_BASE,
                                EUSCI_B_I2C_RECEIVE_INTERRUPT0 +
                                EUSCI_B_I2C_TRANSMIT_INTERRUPT0 +
                                EUSCI_B_I2C_BIT9_POSITION_INTERRUPT +
                                EUSCI_B_I2C_START_INTERRUPT +
                                EUSCI_B_I2C_STOP_INTERRUPT);

    // Enable I2C Module to start operations
    EUSCI_B_I2C_enable(EUSCI_B1_BASE);

    中断例程:

    void USCIB1_ISR(void)
    {
        uint8_t rxByte;

        switch(__even_in_range(UCB1IV, USCI_I2C_UCBIT9IFG))
        {
            case USCI_NONE: // No interrupts break;
                break;

            case USCI_I2C_UCALIFG: // Arbitration lost
                SendLine ("ArbiLost", true);  // send to uart
                break;

            case USCI_I2C_UCNACKIFG: // NAK received (master only)
                SendLine ("NAK", true);
                break;

            case USCI_I2C_UCSTTIFG: // START condition detected with own address (slave mode only)
                SendLine ("START", true);

                // Master wants to talk
                gI2cState = I2C_STATE_MASTER_REQUEST;
                break;

            case USCI_I2C_UCSTPIFG: // STOP condition detected (master & slave mode)
                SendLine ("STOP", true);
                UCB0IFG &= ~UCSTPIFG; // Clear stop condition int flag
                gStartConditionCount = 0;
                gStopCondition = 1;
                break;

            case USCI_I2C_UCRXIFG3: // RXIFG3
                break;

            case USCI_I2C_UCTXIFG3: // TXIFG3
                break;

            case USCI_I2C_UCRXIFG2: // RXIFG2
                break;

            case USCI_I2C_UCTXIFG2: // TXIFG2
                break;

            case USCI_I2C_UCRXIFG1: // RXIFG1
                break;

            case USCI_I2C_UCTXIFG1: // TXIFG1
                break;

            case USCI_I2C_UCRXIFG0: // RXIFG0
                SendLine ("Rx0", true);


                // Received a byte
                rxByte = EUSCI_B_I2C_slaveGetData (EUSCI_B1_BASE);

                PutRxQ (rxByte);
                break;

            case USCI_I2C_UCTXIFG0: // TXIFG0
                SendLine ("Tx0", true);


                if (gI2cState != I2C_STATE_IDLE)
                {
                    // For some reason, there are two interrupt hits per byte being requested by master.
                    // So the index has to accommodate.

                    if (gLastCommandIndex < 4)
                    {

                        EUSCI_B_I2C_slavePutData(EUSCI_B1_BASE, gLastCommandStatus[gLastCommandIndex]);
                        if (gStopCondition == 0)
                        {
                            SendLine ("INC", true);
                            gLastCommandIndex++;
                        }
                        else
                        {
                            SendLine ("NOSTOP", true);
                            EUSCI_B_I2C_slavePutData(EUSCI_B1_BASE, RC_NO_RETURN_CODE); // No valid return code read
                        }
                    }
                    else
                    {
                        SendLine ("NOCODE", true);
                        EUSCI_B_I2C_slavePutData(EUSCI_B1_BASE, RC_NO_RETURN_CODE); // No valid return code read
                    }
                }
                else
                {
                    SendLine ("NOTREADY", true);
                    EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE, RC_RETURN_CODE_NOT_READY); // Not ready. Host should try to read again
                }
                UCB0IFG &= ~UCTXIFG0; // Clear TX0 condition int flag
                break;

            case USCI_I2C_UCBCNTIFG: // Byte count limit reached (UCBxTBCNT)
                SendLine ("CNT", true);
                break;

            case USCI_I2C_UCCLTOIFG: // Clock low timeout - clock held low too long
                SendLine ("CLK", true);
                break;

            case USCI_I2C_UCBIT9IFG: // Generated on 9th bit of a transmit (for debugging)
                SendLine ("9TH", true);
                gI2cState = I2C_STATE_IDLE;
                gStopCondition = 0;

                 gLastCommandIndex = 0;
                break;

            default:
                break;
    }

    谢谢、

    Minh

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

    它会使我感到很臭、因为您很晚才明确地清除 TXIFG。 读取 IV 寄存器会清除相关标志、因此无需再次清除。 更糟糕的是、向 TXBUF 写入数据后、一旦数据被传输到移位寄存器、TXIFG 将再次被置位。 这意味着您很有可能在中断标志引起中断之前清除该中断标志。 你最好有一个比赛条件。