请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号: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; }