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.

[参考译文] MSP430FR5994:ADS112C04的 I2C 问题

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1160599/msp430fr5994-i2c-problem-with-ads112c04

器件型号:MSP430FR5994
主题中讨论的其他器件:ADS112C04

您好!

我 正在尝试从 ADS112C04读取数据。 因此、我编写的函数基本上像 eusci_b_i2c 库中的相应函数一样工作、但具有重复的启动条件。 ADC 的初始化工作正常、我可以写入所有寄存器、IDAC 电流将打开、PGA 也会工作。 我还正确接收到第一个测量值。 但是、当发送 RDATA 命令进行第二次测量时、代码会卡住。

测量由 TimerB 每秒触发四次、这是完整序列:

TimerB 中断->发送 START_SYNC 命令(函数 ADS112C04_Measure)-> DRDY 下降沿 IRQ ->发送 RDATA 并切换至接收(请参阅函数 ADS112C04_Receive)-> I2C RX IRQ ->处理测量数据

该周期在开始时工作一次、第二次卡住(请参阅来源):

bool ADS112C04_init(void)//(uint8_t eUSCI_MODULE)
{
    uint8_t i;
    const uint16_t delay = 80; 
    const uint8_t regSend[8] = {CMD_WREG0, REG0, CMD_WREG1, REG1, CMD_WREG2, REG2, CMD_WREG3, REG3};

    // I2C_ Init
    EUSCI_B_I2C_initMasterParam i2c_master_init = {
       EUSCI_B_I2C_CLOCKSOURCE_SMCLK,
       CS_getSMCLK(),
       EUSCI_B_I2C_SET_DATA_RATE_100KBPS,       
       0,                                       
       EUSCI_B_I2C_NO_AUTO_STOP                 
    };

    ADS112C04_powerOn();

    EUSCI_B_I2C_initMaster(AFE_USCI_BASE, &i2c_master_init);

    EUSCI_B_I2C_clearInterrupt(AFE_USCI_BASE, UCRXIE); // neu

    EUSCI_B_I2C_setSlaveAddress(AFE_USCI_BASE, ADS112C04_ADDRESS);

    EUSCI_B_I2C_setMode(AFE_USCI_BASE,EUSCI_B_I2C_TRANSMIT_MODE);

    EUSCI_B_I2C_enable(AFE_USCI_BASE);

    HWREG16(AFE_USCI_BASE + OFS_UCBxCTLW0) |= UCTXSTT;

    while(HWREG16(AFE_USCI_BASE + OFS_UCBxCTLW0) & UCTXSTT); 

    for (i=0; i<8; i++)
    {
        HWREG16(AFE_USCI_BASE + OFS_UCBxTXBUF) = regSend[i];
        while ((!(HWREG16(AFE_USCI_BASE + OFS_UCBxIFG) & UCTXIFG)) && --timeout);
		if (timeout == 0) return (STATUS_FAIL);
        __delay_cycles(delay); 
    }

    HWREG16(AFE_USCI_BASE + OFS_UCBxCTLW0) |= UCTXSTP;

    EUSCI_B_I2C_clearInterrupt(AFE_USCI_BASE, UCRXIE); 
    EUSCI_B_I2C_enableInterrupt(AFE_USCI_BASE, UCRXIE);

    GPIO_selectInterruptEdge(AFE_EOC_PIN, GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_clearInterrupt(AFE_EOC_PIN);
    GPIO_enableInterrupt(AFE_EOC_PIN);

    return (STATUS_SUCCESS);
}


bool ADS112C04_sendCmd(uint8_t command)
{
    bool timeoutError = false;

    if (!EUSCI_B_I2C_masterSendSingleByteWithTimeout(AFE_USCI_BASE, command, ADS112C04_TIMEOUT)) return (STATUS_FAIL);

    return (STATUS_SUCCESS);
}

bool ADS112C04_measure(void)
{
    bool error = false;

    error = ADS112C04_sendCmd(CMD_START_SYNC);

    return (error);
}

bool ADS112C04_receive(void) // RDATA
{
    uint32_t timeout = ADS112C04_TIMEOUT;

    uint16_t txieStatus = HWREG16(AFE_USCI_BASE + OFS_UCBxIE) & UCTXIE; //Store current transmit interrupt enable

    HWREG16(AFE_USCI_BASE + OFS_UCBxIE) &= ~(UCTXIE); //Disable transmit interrupt enable

    HWREG16(AFE_USCI_BASE + OFS_UCBxCTLW0) |= UCTR +  UCTXSTT; //Send start condition.

    while ((!(HWREG16(AFE_USCI_BASE + OFS_UCBxIFG) & UCTXIFG)) && --timeout); //Poll for transmit interrupt flag
    
    if (timeout == 0) return (STATUS_FAIL); //Check if transfer timed out
    
    HWREG16(AFE_USCI_BASE + OFS_UCBxTXBUF) = CMD_RDATA;//Send single byte data

	timeout = ADS112C04_TIMEOUT; //Reset timeout
	
	/* !!!!!!!
	 THE CODE GETS STUCK IN THE LOOP BELOW
	!!!!!!!! */
    
    while ((!(HWREG16(AFE_USCI_BASE + OFS_UCBxIFG) & UCTXIFG)) && --timeout);//Poll for transmit interrupt flag.
    
    if (timeout == 0) return (STATUS_FAIL); //Check if transfer timed out
    
    HWREG16(AFE_USCI_BASE + OFS_UCBxIFG) &= ~(UCTXIFG); //Clear transmit interrupt flag before enabling interrupt again

    HWREG16(AFE_USCI_BASE + OFS_UCBxIE) |= txieStatus;//Reinstate transmit interrupt enable

     __delay_cycles(64); 

	// Receive

    bytesExpected = 2;
    i2cRxByteCount = 0;
	
    EUSCI_B_I2C_setMode(AFE_USCI_BASE, EUSCI_B_I2C_RECEIVE_MODE);

    HWREG16(AFE_USCI_BASE + OFS_UCBxCTLW0) |= UCTXSTT; // Start

    return(STATUS_SUCCESS);
}

#pragma vector =  AFE_IRQ_VECT 
__interrupt void EUSCI_B_ISR(void)
{
    switch(__even_in_range(AFE_IRQ_REG, USCI_I2C_UCBIT9IFG)) //NEU
    {
        case USCI_NONE:          break;     // Vector 0: No interrupts
        case USCI_I2C_UCALIFG:   break;     // Vector 2: ALIFG
        case USCI_I2C_UCNACKIFG: break;     // Vector 4: NACKIFG
        case USCI_I2C_UCSTTIFG:  break;     // Vector 6: STTIFG
        case USCI_I2C_UCSTPIFG:  break;     // Vector 8: STPIFG
        case USCI_I2C_UCRXIFG3:  break;     // Vector 10: RXIFG3
        case USCI_I2C_UCTXIFG3:  break;     // Vector 12: TXIFG3
        case USCI_I2C_UCRXIFG2:  break;     // Vector 14: RXIFG2
        case USCI_I2C_UCTXIFG2:  break;     // Vector 16: TXIFG2
        case USCI_I2C_UCRXIFG1:  break;     // Vector 18: RXIFG1
        case USCI_I2C_UCTXIFG1:  break;     // Vector 20: TXIFG1
        case USCI_I2C_UCRXIFG0:             // Vector 22: RXIFG0

            if (bytesExpected > 0)
            {
                if (i2cRxByteCount == bytesExpected - 1)
                {
                    // EUSCI_B_I2C_masterReceiveMultiByteFinish
                    HWREG16(AFE_USCI_BASE + OFS_UCBxCTLW0) |= UCTXSTP; // Stop-Bedingung setzen
                }

                i2cRxBuf[i2cRxByteCount] = HWREG16(AFE_USCI_BASE + OFS_UCBxRXBUF);
                i2cRxByteCount++;

                if (i2cRxByteCount == bytesExpected)
                {
                    bytesExpected = 0;
                    i2cRxFlag = true;
                    __bic_SR_register_on_exit(LPM3_bits | GIE);
                }
            }

            break;
        case USCI_I2C_UCTXIFG0:  break;     // Vector 24: TXIFG0
        case USCI_I2C_UCBCNTIFG: break;     // Vector 26: BCNTIFG
        case USCI_I2C_UCCLTOIFG: break;     // Vector 28: clock low timeout
        case USCI_I2C_UCBIT9IFG: break;     // Vector 30: 9th bit
        default: break;
    }
}

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

    根据您的描述、我怀疑您在等待停止请求时发出(新)启动命令、这会导致 I2C 单元出现问题。 当接收到(n+1)个字节时,您将唤醒 main(),因此 UCTXSTP 延迟可能高达(9+1)/100k=100usec。

    我建议您在_receive()的开头添加类似这样的内容:

    >   while (HWREG16 (AFE_USCI_BASE + OFS_UCBxCTLW0)& UCTXSTP);//确保先前的操作完成。

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

    感谢您的快速回答。 我添加了您建议的轮询以停止但未成功。 当到达该点时、停止位已被清除。 此外、在接收最后一个字节(请参阅第138行)之前、我已经在发送停止条件、这是 SLAU208建议的。  

    问题是、发送 RDATA 字节后、ADC 会发送其转换结果、第93行中的 TX 轮询循环将超时、如果删除超时、则会永远循环。 我真的看不到这是没有理由的。

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

    要回答您的问题:[参考用户指南(SLAU367P)图32-12]在发布开始之前、第一个 TXIFG "免费"。 在那之前几乎没有任何事情会出错。 仅在(1) Start has completed (开始已完成)(2) SLA 已确认后才会出现下一个 TXIFG、因此可能会出错。

    常见的问题是:(a)总线有问题、无法发出启动命令(缺少上拉电阻、从器件时钟拉伸、从器件出于某种原因将 SDA 保持在低电平)(b)来自 SLA 字节的 NACK (c)在停止挂起时请求了启动。  

    由于之前的操作成功、我们可能会对上拉/下拉进行折扣、而从数据表声称它从未时钟扩展。 其他故障源自先前的操作、即(我之前错过了此操作) Start/Synch 命令。 在这里、我要提到 sendSingleByte 不会等待其 UCTXSTP 完成。

    您提到一些操作由 IRQ 触发。 您是否在 ISR 内部发布 I2C 操作?