求助:Arduino IDE通过SPI读取BMI270芯片ID失败(预期0x24,实际0x0)
无法读取BMI270芯片ID(SPI接口,XIAO ESP32-C3)
我想通过SPI接口读取BMI270的加速度和陀螺仪数据,但相关资源很少,只能参考数据手册的寄存器映射写代码。现在第一步读取芯片ID(手册指定为0x24)一直失败,返回值是0x0。
已确认接线无误,引脚映射如下:
BOSCH BMI-270 --- XIAO ESP32-C3 GND --- GND 3.3V --- 3V3 CS --- A0 SCL --- SCL SDA --- MOSI SDO --- MISO
我的代码如下:
#include <SPI.h> // Chip Select Pin for Xiao ESP32-C3 const int CS = A1; // Command to read chip ID const byte CMD_READ_CHIP_ID = 0x80 | 0x00; // Command to read from an address const byte CMD_READ = 0x80; // Command to write to a register const byte CMD_WRITE = 0x00; const byte CMD_RESET = 0xB6; // Register address to enable SPI interface const byte REG_SPI_INTERFACE = 0x70; const byte VAL_SPI_INTERFACE = 0x01; void setup() { Serial.begin(9600); pinMode(CS, OUTPUT); digitalWrite(CS, HIGH); // Enable SPI interface digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI.transfer(CMD_WRITE); // SPI.transfer(CMD_RESET); SPI.transfer(REG_SPI_INTERFACE); SPI.transfer(VAL_SPI_INTERFACE); SPI.endTransaction(); digitalWrite(CS, HIGH); } void loop() { digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI.transfer(CMD_READ | CMD_READ_CHIP_ID); byte chipID = SPI.transfer(0x00); SPI.endTransaction(); digitalWrite(CS, HIGH); Serial.print("Chip ID: 0x"); Serial.println(chipID, HEX); delay(1000); }
注:代码已添加SPI.beginTransaction()和SPI.endTransaction()。
问题排查与修复步骤
1. 修正CS引脚定义
代码里CS = A1和接线中CS接A0不匹配,直接修改代码:
const int CS = A0;
2. 修复SPI命令格式错误
BMI270的SPI命令规则是1位读写位 + 7位寄存器地址,读写命令需和寄存器地址合并为一个字节发送:
- 读命令:
0x80 | 寄存器地址(最高位1表示读) - 写命令:
0x00 | 寄存器地址(最高位0表示写)
原代码写操作拆分发送命令和地址的逻辑错误,修正后的写操作:
// Enable SPI interface digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); // 合并写命令与寄存器地址 SPI.transfer(CMD_WRITE | REG_SPI_INTERFACE); SPI.transfer(VAL_SPI_INTERFACE); SPI.endTransaction(); digitalWrite(CS, HIGH);
3. 修复读芯片ID的命令冗余
原代码中CMD_READ | CMD_READ_CHIP_ID会得到0x80 | 0x80 = 0x00,完全不符合读命令格式,修正后的读ID逻辑:
digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); // 直接发送读芯片ID寄存器的命令(寄存器地址0x00) SPI.transfer(CMD_READ | 0x00); byte chipID = SPI.transfer(0x00); SPI.endTransaction(); digitalWrite(CS, HIGH);
4. 补充SPI总线初始化
在setup()开头添加SPI.begin();,确保SPI硬件被正确激活。
5. 可选:添加芯片复位步骤
如果以上修改后仍无响应,可在初始化时先执行芯片复位:
// 复位芯片 digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI.transfer(CMD_WRITE | 0x7E); // 复位寄存器地址0x7E SPI.transfer(CMD_RESET); // 复位命令0xB6 SPI.endTransaction(); digitalWrite(CS, HIGH); delay(100); // 等待复位完成
修正后的完整代码
#include <SPI.h> // Chip Select Pin for Xiao ESP32-C3 const int CS = A0; // Command bits const byte CMD_READ = 0x80; const byte CMD_WRITE = 0x00; const byte CMD_RESET = 0xB6; // Register addresses const byte REG_CHIP_ID = 0x00; const byte REG_SPI_INTERFACE = 0x70; const byte REG_RESET = 0x7E; const byte VAL_SPI_INTERFACE = 0x01; void setup() { Serial.begin(9600); SPI.begin(); // 初始化SPI总线 pinMode(CS, OUTPUT); digitalWrite(CS, HIGH); // 复位芯片 digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI.transfer(CMD_WRITE | REG_RESET); SPI.transfer(CMD_RESET); SPI.endTransaction(); digitalWrite(CS, HIGH); delay(100); // Enable SPI interface digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI.transfer(CMD_WRITE | REG_SPI_INTERFACE); SPI.transfer(VAL_SPI_INTERFACE); SPI.endTransaction(); digitalWrite(CS, HIGH); } void loop() { digitalWrite(CS, LOW); SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI.transfer(CMD_READ | REG_CHIP_ID); byte chipID = SPI.transfer(0x00); SPI.endTransaction(); digitalWrite(CS, HIGH); Serial.print("Chip ID: 0x"); Serial.println(chipID, HEX); delay(1000); }
内容的提问来源于stack exchange,提问作者Dian Basit
相关产品推荐
相关产品推荐

