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.

[参考译文] MSP430FR2676:I2C 通信问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1048222/msp430fr2676-i2c-communication-problem

器件型号:MSP430FR2676

尝试与 IS31FL3236A LED 驱动器通信。 当我与驾驶员交谈时、它将突然停止工作并冻结整个程序。

初始化驱动程序效果很好、 但一旦 LED 开始亮起、软件就会卡住。

通过检查、使用逻辑分析仪、我会得到一个随机 NACK、并且它从不在同一位置(随机位于从器件地址字节或寄存器地址或数据字节之后):

NACK 标志被置位、导致总线忙、SCL 线路变为低电平、所有通信完全停止。

 非常感谢您的任何帮助、我已经勾画了产品系列用户指南和数据表、但我似乎找不到我的答案。

下面是我要使用的 I2C 代码以及 LED 驱动器的数据表。

#include "eusci_iic_driver.h"


// NEED TO TRACK USCI STATUS AND PROVIDE DATA POINTER FOR USE IN ISR
volatile eUSCI_status ui8Status;
uint8_t* pData;
uint8_t ui8DummyRead;

/* ***************************************************************************
 * UCB0_MasterI2C_init
 * INITIALIZE I2C IN MASTER MODE
 * SEE EUSCI_DEF.H FOR SETUP DEFINITIONS
 *
*/
void UCB1_MasterI2C_init(void)
{
    UCB1CTLW0 = UCSWRST; // RESET USCI MODULE
    UCB1CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK; // I2C SINGLE MASTER, SYNC MODE, 7 BIT ADDRS, CLOCK SELECT (DEFINED IN EUSCI_DEF.H)
    UCB1BRW = USCI_B1_BAUD; // SET BAUDRATE
    UCB1CTLW0 &= ~UCSWRST; // ENABLE USCI MODULE
}

/*
 * MASTER I2C WRITE
 * RETURNS: FALSE IF NO ERRORS
 * RETURNS: TRUE IF SLAVE NACK'D
 */
bool UCB1_I2C_write(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
{
    uint8_t ui8index;

    UCB1CTLW0 |= UCSWRST;
    UCB1CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK; // I2C SINGLE MASTER, SYNC MODE, 7 BIT ADDRS, CLOCK SELECT (DEFINED IN EUSCI_DEF.H)
    UCB1CTLW1 |= UCASTP_1;
    UCB1TBCNT = ui8ByteCount + 1;
    UCB1I2CSA = ui8Addr;
    UCB1CTLW0 &= ~UCSWRST;
    UCB1CTLW0 |= (UCTR + UCTXSTT);

    while(!(UCB1IFG & UCTXIFG)); //WAIT FOR THE FIRST TXBUF EMPTY INTERRUPT
    UCB1TXBUF = ui8Reg; //LOAD TXBUF WITH THE TARGET REGISTER
    for(ui8index = 0; ui8index < ui8ByteCount; ui8index++)
    {
        while(!(UCB1IFG & UCTXIFG0));
            UCB1TXBUF = Data[ui8index];
    }
    while(!(UCB1IFG & UCTXIFG));
    while (!(UCB1IFG & UCBCNTIFG));
    UCB1CTL1 |= UCTXSTP;
    while (!(UCB1IFG & UCSTPIFG));     // Ensure stop condition got sent
    UCB1CTL1  |= UCSWRST;

    return(true);
}

/*
 * MASTER I2C READ
 * RETURNS: FALSE IF NO ERRORS
 * RETURNS: TRUE IF SLAVE NACK'D
 */
bool UCB1_I2C_read(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
{
    uint8_t ui8index;

    UCB1CTLW0 |= UCSWRST;
    UCB1TBCNT = 0x0002; // SETUP THE NUMBER OF BYTES TO RECEIVE (CAN ONLY BE DONE HERE WHEN EUSCI IN RESET)
    UCB1CTLW1 |= UCASTP_1; // GENERATE AUTOMATIC STOP BIT WHEN UCB0TBCNT = TARGET
    UCB1I2CSA = ui8Addr; // LOAD THE DEVICE SLAVE ADDRESS
    UCB1CTLW0 &= ~UCSWRST; // RESUME
    UCB1CTLW0 |= (UCTR + UCTXSTT);
    while(!(UCB1IFG & UCTXIFG)); // WAIT FOR THE FIRST TXBUF EMPTY INTERRUPT BEFORE LOADING TARGET REGISTER
    UCB1TXBUF = ui8Reg; // LOAD TXBUF WITH THE TARGET REGISTER
    while(!(UCB1IFG & UCTXIFG));
    UCB1CTL1 &= ~UCTR; //TURN OFF TRANSMIT (ENABLE RECEIVE)
    UCB1CTL1 |= UCTXSTT; // GENERATE (RE-)START BIT
    while(!(UCB0IFG & UCRXIFG0));

    for(ui8index = 0; ui8index < ui8ByteCount - 1; ui8index++)
    {
        while(!(UCB1IFG & UCRXIFG0));
        Data[ui8index] = UCB0RXBUF;
        if(ui8index == ui8ByteCount - 1)
        {
            UCB1CTL1 |= UCTXSTP;    //send stop after next RX
        }
    }

    UCB1CTLW0 |= UCTXSTP;           //send stop after next RX
    while(!(UCB1IFG & UCRXIFG));
    Data[ui8index] = UCB1RXBUF;
    while (!(UCB1IFG & UCSTPIFG));  // Ensure stop condition got sent
    UCB1CTL1  |= UCSWRST;
    return(true);
}

#ifndef EUSCI_IIC_DRIVER_H_
#define EUSCI_IIC_DRIVER_H_
#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>
#include "driverlib.h"
#define USCI_B1_BAUD 5

typedef enum {
    eUSCI_IDLE=0,
    eUSCI_SUCCESS = 0,
    eUSCI_BUSY =1,
    eUSCI_NACK=2,
    eUSCI_STOP,
    eUSCI_START
}eUSCI_status;

void UCB1_MasterI2C_init(void);
bool UCB1_I2C_write(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount);
bool UCB1_I2C_read(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount);


#endif

e2e.ti.com/.../IS31FL3236A_5F00_DS.pdf

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

    软件挂起的原因是您的传输代码未捕捉到 NACK。

    由于您说问题发生在 LED 开始亮起后、因此可能是电源问题。 电流不足、甚至不足以导致意外位置的电压降。 您应该仔细检查您的电源接线。

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

    尊敬的 David:  

    感谢您的回答。

    这也是我的想法、但即使我启用中断并处理通过添加以下内容引发的 NACK:

    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCIB1_ISR(void)
    {  switch(__even_in_range(UCB1IV,USCI_I2C_UCBIT9IFG))
        {
            case USCI_I2C_UCNACKIFG:
                    UCB1CTLW0 |= UCTXSTP;
                    //UCB1IFG &= ~UCTXIFG;
                    //UCB1CTL1 |= UCTXSTT;                //resend start if NACK
            break;                                      // Vector 4: NACKIFG break;
            default: break;
        }
    }

    它仍然 不允许我重新接通总线。 我应该"做什么"来处理 NACK、以便我可以为另一个事务重置总线?

    我尚未研究电源问题、因为我的电路板 由台式电源供电。  但 我将在明天对此进行探讨。 我怀疑这不是问题、因为 使用不同的 i2c 代码、我能够进一步提高(将所有 LED 照明到全亮度)。

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

    注意:LED 驱动器数据表专门指出、如果接收到 NACK、则应发送 STOP 以提早结束事务。 但是、如果我尝试此操作、由于某种原因无法发送停止位。

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

    除了发送停止、您还需要使数据传输从头开始。 传输循环正在等待 TXIFG。

    不同的 I2C 代码? 如果可行、您为什么会对此表示不理解?

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

    尊敬的 David:

    我仍然无法到达正在发生的事情的底部。 我的 I2C 现在运行正常、但是、我用于电容式模块的电容式传感器似乎 突然停止响应。  如果您能够直接给我发送消息、我将不胜感激、因此我可以向您发送我的项目的完整代码、您可能会对导致此问题的原因有更深入的了解。

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

    你(们)好   

    您的 I2C 是否有任何问题?  您可以提交另一篇关于电容问题的文章、供每个人参考类似的问题。