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.

[参考译文] MSP430G2553:使用 I2C 与 MPU6500进行通信以接收数据的正确方式

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1355935/msp430g2553-correct-way-of-receiving-data-using-i2c-to-communicate-with-mpu6500

器件型号:MSP430G2553

我当前正在尝试使用 I2C 从陀螺仪(MPU6500)读取数据。 我已尝试读取器件的 WHO_AM_I 寄存器、但会返回正确的值。 当我在调试模式下监视读数时、似乎在编程的前~15秒内给出了正确的值。 但是、随着时间的推移、我开始获得非常大的角度读数、这些读数完全不正确。  

下面是我用于配置和接收字节的 i2c.c 文件。  

// Function to config I2C regs - 400 kHz operating freq
void initI2C(void) {

    P1SEL |= SCL + SDA;                         // Config P1.6 SCL and 1.7 SDA
    P1SEL2 |= SCL + SDA;
    UCB0CTL1 |= UCSWRST;                        // Enable SW reset - known state
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // Make MCU master & put in synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST;              // SMCLK approx 1 MHz
    UCB0BR0 = 3;                                // /3 to get fast rate approx 400 kHz
    UCB0BR1 = 1;
    UCB0I2CSA = MPU_SLAVE_ADDRESS;              // Set slave address of mpu6050
    UCB0CTL1 &= ~UCSWRST;                       // Exit SW reset now that registers are configured
}

// Function to check if I2C is busy - WARNING:
// According to MSP430 Erreta " the UCBBUSY bit might get stuck to 1" - may cause issues
int IsI2CBusy(){
        if(UCB0STAT & UCBBUSY){
            return 1;                           // BUS BUSY
        } else{
            return 0;                           // BUS NOT BUSY
        }
}

// Function to read a single byte of given I2C Slave Address
char ReceiveByte(char register_address){

    volatile char byte;
    while (UCB0CTL1 & UCTXSTP);                 // Wait for our prev stop condition to be sent (just in case..)
    UCB0CTL1 |= UCTR + UCTXSTT;                 // Lets start in transmit MODE
    while((IFG2 & UCB0TXIFG) == 0);             // Wait for MPU66050 Device Address to be sent
    UCB0TXBUF = register_address;               // After we get ACK, lets send register address we want to read
    while((IFG2 & UCB0TXIFG) == 0);             // Wait for ACK...
    UCB0CTL1 &= ~UCTR ;                         // Now we can receive data from the register address
    UCB0CTL1 |= UCTXSTT + UCTXNACK;             // Send START and we respond with NACK for single byte read
    while (UCB0CTL1 & UCTXSTT);                 // Wait for start to complete...
    UCB0CTL1 |= UCTXSTP;                        // Send stop
    while(!(IFG2 & UCB0RXIFG));                 // Wait until we receive
    byte = UCB0RXBUF;                           // Read the byte
    return byte;

}

这是我的函数、它从陀螺仪获取 Z 读数、陀螺仪对应于寄存器0x47 (MSB)和0x48 (LSB)。 调试后、似乎当获得大角度读数时、会从 MSB 寄存器(例如0xAA)和 LSB 寄存器中读取非常大的值。 Im 对角度跟踪在程序开始时如何起作用感到困惑、然后在十几秒或两秒后完全降级。  

volatile float GetZReading(volatile float error){

    volatile char gyro_z_msb, gyro_z_lsb;
    int16_t gyro_raw_z = 0.0;
    volatile float gyro_z;

    gyro_z_msb = ReceiveByte(0x47);
    gyro_z_lsb = ReceiveByte(0x48);

    gyro_raw_z = (gyro_z_msb<<8) | gyro_z_lsb;

    gyro_z = (gyro_raw_z/GYRO_SF) - error;

    return gyro_z;

}

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

    读取类似这样的传感器时、您始终希望在单个事务中检索多字节数据。 否则、数据可以来自不同的样本。

    这将是仅包含陀螺仪数据的六个字节。

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

    感谢您的建议-我将尝试按照您的建议更新代码。 我一直在做更多的调试、当我得到不正确的读数时、SCLLOW 标志似乎为高电平。 SCL 线似乎卡在低电平、这似乎是问题的原因。

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

    当我在收到错误读数时读取 WHO_AM_I 寄存器时、它也会读取到错误的值0xAA。