使用指针读取MPU9250寄存器失败,求原因解析
为什么用空指针读取MPU9250 WHO_I_AM寄存器会得到错误值?
我尝试用Asukiaaa的Arduino库通过I2C读取MPU9250的WHO_I_AM寄存器,库中readId函数的定义如下:
uint8_t MPU9250_asukiaaa::readId(uint8_t *id) { beginWireIfNull(); return i2cRead(address, MPU9250_ADDR_WHOAMI, 1, id); }
根据芯片 datasheet,该寄存器的预期返回值为0x71。
错误写法(返回0x61)
尝试用空指针存储寄存器值的代码:
#include <MPU9250_asukiaaa.h> #include <Adafruit_BMP280.h> Adafruit_BMP280 bmp; // I2C MPU9250_asukiaaa mySensor; uint8_t *Id=NULL; void setup() { Serial.begin(9600); while (!Serial); #ifdef _ESP32_HAL_I2C_H_ // For ESP32 Wire.begin(SDA_PIN, SCL_PIN); mySensor.setWire(&Wire); #else Wire.begin(); mySensor.setWire(&Wire); #endif bmp.begin(0x76); mySensor.beginAccel(); mySensor.beginGyro(); mySensor.beginMag(); } void loop() { mySensor.readId(Id); Serial.print(*Id,HEX); }
正确写法(返回0x71)
改用普通变量并传入其地址的代码:
#include <MPU9250_asukiaaa.h> #include <Adafruit_BMP280.h> Adafruit_BMP280 bmp; // I2C MPU9250_asukiaaa mySensor; uint8_t Id=0; void setup() { Serial.begin(9600); while (!Serial); #ifdef _ESP32_HAL_I2C_H_ // For ESP32 Wire.begin(SDA_PIN, SCL_PIN); mySensor.setWire(&Wire); #else Wire.begin(); mySensor.setWire(&Wire); #endif bmp.begin(0x76); mySensor.beginAccel(); mySensor.beginGyro(); mySensor.beginMag(); } void loop() { mySensor.readId(&Id); Serial.print(Id,HEX); }
差异原因
核心问题是空指针uint8_t *Id=NULL;没有指向有效且可写入的内存空间:
- 错误写法中,调用
mySensor.readId(Id)时,函数内部的i2cRead尝试将寄存器值写入Id指向的地址,但Id是NULL(空地址),这属于C/C++中的未定义行为——程序可能崩溃,也可能误写入随机内存地址,你读出的0x61就是该随机地址中的垃圾值。 - 正确写法里,
uint8_t Id=0;定义了一个实际的uint8_t变量,它在内存中占据1字节的有效空间。调用mySensor.readId(&Id)时,传入的是这个变量的真实内存地址,i2cRead可以安全地将寄存器值写入该地址,因此能得到正确的0x71。
总结:指针仅用于存储内存地址,必须先让它指向一块真实存在的内存区域,才能用来存储数据。空指针没有指向任何有效内存,写入操作完全无效,读取结果自然错误。
内容的提问来源于stack exchange,提问作者AF2021
相关产品推荐
相关产品推荐

