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.

[参考译文] MSP430G2533:需要使用 I2C_MSP430G2533写入从寄存器 Master_Write_Reg

Guru**** 2473260 points
Other Parts Discussed in Thread: MSP430G2533

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1321459/msp430g2533-need-to-write-to-a-slave-register-using-i2c_master_write_reg

器件型号:MSP430G2533

大家好。

我花了整整三天的时间尝试解决这个问题。 我一直在对 MSP430G2533进行编程、以成功完成许多工作、尤其是对 PWM 等。 我还可以对 I2C 主设备进行编程、以便与 BQ 电量监测计芯片通信并获取其充电状态... 只需远程读取一个寄存器,使用函数 Master_Read。

但我需要它向 KXJ3-1057加速计发送几个字节、以便设置它、在运动时发送中断、以及其他事项、即:向加速计中的寄存器发送一个值。 我可以使 WHO_AM_I 从加速计成功读取(使用 Master_Read 进行单字节读取操作)、因此硬件正常。 但是、如果 使用  I2C_EVM 函数传输超过一个字节 Master_Write_Reg、则 不传输任何数据。

IDE 为 CCS 版本:12.5.0.00007、并且编译器为 TI 编译器 V21.6.0.LTS。

I2C_I2C_EVM 这里是否有明显错误的地方 Master_Write_Reg? 如有任何帮助,将不胜感激。  

此处提供代码:

/********************** I2C LOW LEVEL DEFINITIONS *********************************/

//******************************************************************************
// Reading and Writing Functions ***********************************************
//******************************************************************************

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;
    IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
    IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
    IE2 |= UCB0TXIE;                        // Enable TX interrupt

    UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
    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;

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

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

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;
    IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
    IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
    IE2 |= UCB0TXIE;                        // Enable TX interrupt

    UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts

    return MasterMode;
}

//******************************************************************************
// Copy Array for storing it ***************************************************
//******************************************************************************

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];
    }
}

/****************************************************************************************************
    ////////////////// Interrupt Service Routines (ISR) for Button and Timers ///////////////////////
****************************************************************************************************/

/******************************************************************************
    Function:      ISR - USCIAB0RX_ISR (I2C)
    Description:   I2C Interrupt For Start, Restart, Nack, Stop
    Inputs:        None
    Outputs:       None
******************************************************************************/
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
    if (UCB0STAT & UCNACKIFG)
    {
        UCB0STAT &= ~UCNACKIFG;                     // Clear NAK Flags
    }
    if (UCB0STAT & UCSTPIFG)                        // Stop or NACK Interrupt
    {
        UCB0STAT &=
            ~(UCSTTIFG + UCSTPIFG + UCNACKIFG);     // Clear START/STOP/NACK Flags
    }
    if (UCB0STAT & UCSTTIFG)
    {
        UCB0STAT &= ~(UCSTTIFG);                    // Clear START Flags
    }
}

/******************************************************************************
    Function:      ISR - USCIAB0TX_ISR (I2C)
    Description:   I2C Interrupt For Received and Transmitted Data
    Inputs:        None
    Outputs:       None
******************************************************************************/

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)

{
  if (IFG2 & UCB0RXIFG)                 // Receive Data Interrupt
  {
      uint8_t rx_val = UCB0RXBUF;       // Must read from UCB0RXBUF

      if (RXByteCtr)
      {
          ReceiveBuffer[ReceiveIndex++] = rx_val;
          RXByteCtr--;
      }

      if (RXByteCtr == 1)
      {
          UCB0CTL1 |= UCTXSTP;
      }
      else if (RXByteCtr == 0)
      {
          IE2 &= ~UCB0RXIE;
          MasterMode = IDLE_MODE;
          __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
      }
  }
  else if (IFG2 & UCB0TXIFG)            // Transmit Data Interrupt
  {
      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:
              IE2 |= UCB0RXIE;              // Enable RX interrupt
              IE2 &= ~UCB0TXIE;             // Disable TX interrupt
              UCB0CTL1 &= ~UCTR;            // Switch to receiver
              MasterMode = RX_DATA_MODE;    // State state is to receive data
              UCB0CTL1 |= UCTXSTT;          // Send repeated start
              if (RXByteCtr == 1)
              {
                  //Must send stop since this is the N-1 byte
                  while((UCB0CTL1 & UCTXSTT));
                  UCB0CTL1 |= UCTXSTP;      // Send stop condition
              }
              break;

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

          default:
              __no_operation();
              break;
      }
  }
}

/********************** I2C LOW LEVEL DEFINITIONS *********************************/

//******************************************************************************
// Reading and Writing Functions ***********************************************
//******************************************************************************

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;
    IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
    IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
    IE2 |= UCB0TXIE;                        // Enable TX interrupt

    UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
    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;

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

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

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;
    IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);       // Clear any pending interrupts
    IE2 &= ~UCB0RXIE;                       // Disable RX interrupt
    IE2 |= UCB0TXIE;                        // Enable TX interrupt

    UCB0CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts

    return MasterMode;
}

//******************************************************************************
// Copy Array for storing it ***************************************************
//******************************************************************************

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];
    }
}

/****************************************************************************************************
    ////////////////// Interrupt Service Routines (ISR) for Button and Timers ///////////////////////
****************************************************************************************************/

/******************************************************************************
    Function:      ISR - USCIAB0RX_ISR (I2C)
    Description:   I2C Interrupt For Start, Restart, Nack, Stop
    Inputs:        None
    Outputs:       None
******************************************************************************/
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
    if (UCB0STAT & UCNACKIFG)
    {
        UCB0STAT &= ~UCNACKIFG;                     // Clear NAK Flags
    }
    if (UCB0STAT & UCSTPIFG)                        // Stop or NACK Interrupt
    {
        UCB0STAT &=
            ~(UCSTTIFG + UCSTPIFG + UCNACKIFG);     // Clear START/STOP/NACK Flags
    }
    if (UCB0STAT & UCSTTIFG)
    {
        UCB0STAT &= ~(UCSTTIFG);                    // Clear START Flags
    }
}

/******************************************************************************
    Function:      ISR - USCIAB0TX_ISR (I2C)
    Description:   I2C Interrupt For Received and Transmitted Data
    Inputs:        None
    Outputs:       None
******************************************************************************/

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)

{
  if (IFG2 & UCB0RXIFG)                 // Receive Data Interrupt
  {
      uint8_t rx_val = UCB0RXBUF;       // Must read from UCB0RXBUF

      if (RXByteCtr)
      {
          ReceiveBuffer[ReceiveIndex++] = rx_val;
          RXByteCtr--;
      }

      if (RXByteCtr == 1)
      {
          UCB0CTL1 |= UCTXSTP;
      }
      else if (RXByteCtr == 0)
      {
          IE2 &= ~UCB0RXIE;
          MasterMode = IDLE_MODE;
          __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
      }
  }
  else if (IFG2 & UCB0TXIFG)            // Transmit Data Interrupt
  {
      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:
              IE2 |= UCB0RXIE;              // Enable RX interrupt
              IE2 &= ~UCB0TXIE;             // Disable TX interrupt
              UCB0CTL1 &= ~UCTR;            // Switch to receiver
              MasterMode = RX_DATA_MODE;    // State state is to receive data
              UCB0CTL1 |= UCTXSTT;          // Send repeated start
              if (RXByteCtr == 1)
              {
                  //Must send stop since this is the N-1 byte
                  while((UCB0CTL1 & UCTXSTT));
                  UCB0CTL1 |= UCTXSTP;      // Send stop condition
              }
              break;

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

          default:
              __no_operation();
              break;
      }
  }
}

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

    您的 main()程序是什么样子的? 我问,因为 I2C_LPM0()似乎在结尾遗漏了 Master_Read 等待(如 i2c_standard_master 中所示)。 如果你在这里或主函数中没有这样做,并且你的 main()在 WriteReg 后面做了 ReadReg ,那么你很可能会在读取完成之前开始写入,这会使 I2C 单元混淆。