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.

TMP112读取时序不对,能出结果,多9个时钟

Other Parts Discussed in Thread: TMP112, MSP430FR2433

最近用MSP430FR2433+TMP112测试,发现一个很奇怪的问题,在读取TMP112的温度寄存器的2字节数据后,又有9个时钟信号,对应的·SDA一直是高电平,这时UCB0RXBUF里面会变成0xFF,而且必须把这个0xFF给读取出来,否则第二次读取的话发送开始信号后无法进入中断。一直没找到问题所在。

IIC驱动函数如下(参考官方例程):

#include "iic.h"
/* Used to track the state of the software state machine*/
I2C_Mode MasterMode = IDLE_MODE;

/* The Register Address/Command to use*/
uint8_t TransmitRegAddr = 0;

/* ReceiveBuffer: Buffer used to receive data in the ISR
 * RXByteCtr: Number of bytes left to receive
 * ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
 * TransmitBuffer: Buffer used to transmit data in the ISR
 * TXByteCtr: Number of bytes left to transfer
 * TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
 * */
uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;

//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************

void initI2C()
{
    UCB0CTLW0 = UCSWRST;                      // Enable SW reset
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
    UCB0BRW = 0x000A;                         // fSCL = SMCLK/10 = ~100kHz
    UCB0I2CSA = SLAVE_ADDR;                   // Slave Address
    UCB0CTLW0 &= ~UCSWRST;                    // Clear SW reset, resume operation
    UCB0IE |= UCNACKIE;
}

I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count)
{
    /* Initialize state machine */
    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;
    RXByteCtr = count;
    TXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;
    UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
    UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
    UCB0IE |= UCTXIE;                        // Enable TX interrupt

    UCB0CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
    __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
    __no_operation();                       // Set breakpoint >>here<< and
    return MasterMode;
}

I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count)
{
    /* Initialize state machine */
    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;

    //Copy register data to TransmitBuffer
    CopyArray(reg_data, TransmitBuffer, count);

    TXByteCtr = count;
    RXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;
    UCB0IFG &= ~(UCTXIFG + UCRXIFG);         // Clear any pending interrupts
    UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
    UCB0IE |= UCTXIE;                        // Enable TX interrupt

    UCB0CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
    __bis_SR_register(LPM0_bits + GIE);      // Enter LPM0 w/ interrupts
    __no_operation();                       // Set breakpoint >>here<< and
    return MasterMode;
}

I2C_Mode I2C_Master_ReadData(uint8_t dev_addr, uint8_t count)
{
    /* Initialize state machine */
    MasterMode = RX_DATA_MODE;
    RXByteCtr = count;
    TXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;

    UCB0IFG &= ~(UCTXIFG + UCRXIFG);         // Clear any pending interrupts
    UCB0IE |= UCRXIE;                       // Disable RX interrupt
    UCB0CTLW0 &= ~UCTR;                     // Switch to receiver
    while (UCB0CTL1 & UCTXSTP);             // Ensure stop condition got sent
    UCB0CTLW0 |= UCTXSTT;                   // I2C RX, start condition
    __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts
    __no_operation();                       // Set breakpoint >>here<< and
    return MasterMode;
}
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
{
    uint8_t copyIndex = 0;
    for (copyIndex = 0; copyIndex < count; copyIndex++)
    {
        dest[copyIndex] = source[copyIndex];
    }
}

//******************************************************************************
// I2C Interrupt ***************************************************************
//******************************************************************************

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  //Must read from UCB0RXBUF
  uint8_t rx_val = 0;
  switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
  {
    case USCI_NONE:          break;         // Vector 0: No interrupts
    case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
         UCB0CTL1 |= UCTXSTP;               // I2C start condition
         UCB0IFG = 0;                            // Clear All USCI_B0 flags
         __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM
         MasterMode = NACK_MODE;                // State state is to receive data
      break;
    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
        rx_val = UCB0RXBUF;
        if (RXByteCtr)
        {
          ReceiveBuffer[ReceiveIndex++] = rx_val;
          RXByteCtr--;
        }

        if (RXByteCtr == 1)
        {
          UCB0CTLW0 |= UCTXSTP;
        }
        else if (RXByteCtr == 0)
        {
          UCB0IE &= ~UCRXIE;
          //UCB0IFG &=~ UCRXIFG;
          rx_val = UCB0RXBUF;            //这个地方不能注释,要把UCB0RXBUF里面的0xff读出来,不然连续会进不了中断
          MasterMode = IDLE_MODE;
          __bic_SR_register_on_exit(LPM0_bits);      // Exit LPM0
        }
        break;
    case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
        switch (MasterMode)
        {
          case TX_REG_ADDRESS_MODE:
              UCB0TXBUF = TransmitRegAddr;
              if (RXByteCtr)
                  MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
              else
                  MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
              break;

          case SWITCH_TO_RX_MODE:
              UCB0IE |= UCRXIE;              // Enable RX interrupt
              UCB0IE &= ~UCTXIE;             // Disable TX interrupt
              UCB0CTLW0 &= ~UCTR;            // Switch to receiver
              MasterMode = RX_DATA_MODE;    // State state is to receive data
              UCB0CTLW0 |= UCTXSTT;          // Send repeated start
              if (RXByteCtr == 1)
              {
                  //Must send stop since this is the N-1 byte
                  while((UCB0CTLW0 & UCTXSTT));
                  UCB0CTLW0 |= UCTXSTP;      // Send stop condition
              }
              break;

          case TX_DATA_MODE:
              if (TXByteCtr)
              {
                  UCB0TXBUF = TransmitBuffer[TransmitIndex++];
                  TXByteCtr--;
              }
              else
              {
                  //Done with transmission
                  UCB0CTLW0 |= UCTXSTP;     // Send stop condition
                  MasterMode = IDLE_MODE;
                  UCB0IE &= ~UCTXIE;                       // disable TX interrupt
                  __bic_SR_register_on_exit(LPM0_bits);      // Exit LPM0
              }
              break;

          default:
              __no_operation();
              break;
        }
        break;
    default: break;
  }
}
读取函数如下:
void Tmp102_Read_Temp()
{
    I2C_Mode TempMode = IDLE_MODE;
    uint8_t reg_data = 0x00;
    //I2C_Master_ReadReg(TMP102_ADDRESS, Temperature , 2);       //也可单独能出结果,但是在发送寄存器地址后没有STOP操作与TMP112时序对不上,查看了TMP117的时序在发送寄存器地址后可以直接RESTART,不用STOP操作
    I2C_Master_WriteReg(TMP102_ADDRESS, Temperature, 0 , 0);
    I2C_Master_ReadData(TMP102_ADDRESS , 2);
//    while(1)
//    {
//        TempMode = I2C_Master_WriteReg(TMP102_ADDRESS, Temperature, 0 , 0);
//        TempMode = I2C_Master_ReadData(TMP102_ADDRESS , 2);
//        __delay_cycles(10000);
//    }
}

  • 请问上拉电阻的值是多少?根据TMP112数据表,应为5 kOhm 。还有一些注意事项:

    1 应该实施OSCFault标志检查,如下所示

    do
    {
    IFG1 &= ~OFIFG; // Clear OSCFault flag
    for (i = 0xFF; i > 0; i--); // Time for flag to set
    }
    while (IFG1 & OFIFG); // OSCFault flag still set?

    2 在发送启动条件之前,请确保已发送停止条件(while (UCB0CTL1 & UCTXSTP);)。发送停止条件相同。

    3 您只发送一个从设备地址,后跟一个字节(指针寄存器),而没有发送任何数据字节。然后,在发送停止条件之前过渡到接收模式。这很可能是您仅收到0xFF响应的原因。