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.

[参考译文] TMS320F280049C:I2C_getStopConditionStatus 始终返回 true

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1272822/tms320f280049c-i2c_getstopconditionstatus-always-returns-true

器件型号:TMS320F280049C

我有  使用 I2C_INT_STOP_Condition 和 2C_INT_NO_ACK 中断的 I2C 代码。

在中断处理程序中、当我获取 2C_INT_NO_ACK 时、我 会调用 I2C_sendStopCondition、以便接下来获取 I2C_INT_STOP_Condition 中断。

我这样做是为了在单点(停止条件)处理消息的每一端并启动新的传输。

现在、 NACKed 消息后下一次传输失败的时间大约有一半。  

为了解决这个问题、我尝试 在中断处理程序中添加一个 while 循环、在它启动新的(有时失败)消息之前轮询 I2C_getStopConditionStatus。

这解决了问题、但是、对于其他 I2C 器件、有时这种 while 循环会卡住、因为 I2C_getStopConditionStatus 在某些情况下似乎总是返回 true。

什么会导致 I2C_getStopConditionStatus 从不返回 FALSE?

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

    您好、Kustaa、

    根据参考手册对 I2CMDR 寄存器的说明(这是 I2C_getStopConditionStatus 函数使用的内容):

    您能告诉我您的 I2C 配置吗? F28004x I2C 是设置为控制器还是目标? 是接收还是传输? 它使用哪种串行格式模式?

    此致、

    阿米尔·奥马尔

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

    您好!

    以下是初始化 I2C 控制器的方式:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void init_i2ca() {
    Interrupt_disable(INT_I2CA);
    Interrupt_disable(INT_I2CA_FIFO);
    I2C_disableInterrupt(I2CA_BASE, I2C_INT_NO_ACK);
    I2C_disableInterrupt(I2CA_BASE, I2C_INT_STOP_CONDITION);
    g_i2cbus_endp.m_trnx_idx = 0;
    g_i2cbus_endp.m_receive = false;
    I2C_disableModule(I2CA_BASE);
    I2C_initMaster(I2CA_BASE, DEVICE_SYSCLK_FREQ, 100000, I2C_DUTYCYCLE_50);
    I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
    I2C_setDataCount(I2CA_BASE, 0);
    I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8);
    I2C_disableFIFO(I2CA_BASE);
    I2C_enableFIFO(I2CA_BASE);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    这是我的中断处理程序:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    __interrupt void i2c_ISR(void) {
    uint32_t istat = I2C_getInterruptStatus(I2CA_BASE);
    if (istat & I2C_INT_STOP_CONDITION) {
    GPIO_togglePin(39);
    I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_STOP_CONDITION);
    i2c_handle_received_data();
    i2c_start_next_transfer();
    GPIO_togglePin(39);
    }
    if (istat & I2C_INT_NO_ACK) {
    GPIO_togglePin(39);
    I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_NO_ACK);
    I2C_clearStatus(I2CA_BASE, I2C_STS_NO_ACK);
    I2C_disableFIFO(I2CA_BASE);
    I2C_enableFIFO(I2CA_BASE);
    I2C_sendStopCondition(I2CA_BASE);
    GPIO_togglePin(39);
    }
    if (istat & I2C_INT_ARB_LOST) {
    I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_ARB_LOST);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    这用于处理在获取停止条件中断时接收/接收新消息:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void i2c_start_next_transfer() {
    I2C_Trxn_t *trxn = get_next_transfer(&g_i2cbus_endp);
    if (trxn) {
    while(I2C_getStopConditionStatus(I2CA_BASE))
    GPIO_togglePin(39);
    //g_debug_x = trxn->m_debug;
    I2C_disableFIFO(I2CA_BASE);
    I2C_enableFIFO(I2CA_BASE);
    if (trxn->m_send) {
    I2C_setSlaveAddress(I2CA_BASE, trxn->m_addr);
    I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
    I2C_setDataCount(I2CA_BASE, trxn->m_data_len);
    uint16_t i;
    for (i = 0; i < trxn->m_data_len; i++) {
    I2C_putData(I2CA_BASE, trxn->m_data[i]);
    }
    //I2C_setFIFOInterruptLevel(I2CA_BASE, I2C_FIFO_TXEMPTY, I2C_FIFO_RXFULL);
    } else {
    I2C_setSlaveAddress(I2CA_BASE, trxn->m_addr);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    它是在上面的 int  

    while (I2C_getStopConditionStatus (I2CA_BASE))

    代码有时会卡住。

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

    您好、Kustaa、

    它是在上面的 int  

    while (I2C_getStopConditionStatus (I2CA_BASE))

    代码有时会卡住。

    [/报价]

    根据寄存器描述、STP 位在停止条件生成后自动清零。 我不确定为什么 在您的设备上有时不会清除它。 就从器件发送的有效传输而言、您是否在示波器上验证了这一点?  发送完成后应立即产生停止条件(见下文):

     也要确保 I2C 外设未处于复位状态(我不确定这里是否会发生这种情况、但这 会阻止 I2C 外设检测启动/停止条件)。

    此致、

    阿米尔·奥马尔

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

    您说停止条件的一部分取决于我要通信的总线上的器件?  
    因此、在中断服务例程中、像我这样的(可能)无限循环是不可接受的?
    我的思维模型是停止条件由 I2C 控制器单独生成、因此始终会发生、环路将会退出。
    除了实现超时之外、是否有办法检查总线是否处于"不良"状态、以及是否应终止循环?

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

    您好、Kustaa、

    为了有一个停止条件、SDA 和 SCL 线路的控制器需要将它们升高到高电平(如之前的图像所示)。 如果 您指定数据和时钟线路的范围、但没有发生这种情况、则将不会获得停止条件、并且 STP 位也不会被清除。

    除了实现超时之外,是否有其他方法可以检查总线是否处于"坏"状态以及是否应终止循环?
    [/报价]

    您可以向 while 循环添加一些逻辑来确定此情况、例如、如果需要、通过运行带有 CPU 计时器的计数器来创建某种超时。 我不认为有这样的硬件、因此您需要进行软件实施。

    此致、

    阿米尔·奥马尔