要使用硬连线的I2C0接口读取NuMaker_IoT_M487开发板上BME280传感器的芯片ID,请按照以下步骤操作:
1. 硬件确认
- I2C接口:BME280通过I2C0接口连接(SDA=PB4, SCL=PB5)。
- 传感器地址:
BME280的I2C地址取决于SDO引脚电平:
- SDO接地 → 0x76 (写地址
0xEC,读地址 0xED)
- SDO接VDD → 0x77 (写地址
0xEE,读地址 0xEF)
- 芯片ID寄存器:
0xD0(返回1字节ID,BME280应为0x60)。
2. 初始化I2C0控制器
#include "NuMicro.h"
void I2C0_Init(void) {
// 使能I2C0时钟
CLK_EnableModuleClock(I2C0_MODULE);
// 配置PB4(SDA)和PB5(SCL)为I2C0功能
SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB4MFP_Msk | SYS_GPB_MFPL_PB5MFP_Msk);
SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB4MFP_I2C0_SDA | SYS_GPB_MFPL_PB5MFP_I2C0_SCL);
// 配置I2C0:主机模式,100kHz时钟
I2C_Open(I2C0, 100000);
}
3. 读取芯片ID函数
uint8_t BME280_ReadChipID(void) {
uint8_t id = 0;
// 步骤1: 发送起始条件 + 设备写地址 (0xEC)
I2C_START(I2C0);
I2C_WAIT_READY(I2C0);
I2C_SET_DATA(I2C0, 0xEC); // 写地址
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
I2C_WAIT_READY(I2C0);
// 步骤2: 发送寄存器地址 (0xD0)
I2C_SET_DATA(I2C0, 0xD0); // Chip ID寄存器
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
I2C_WAIT_READY(I2C0);
// 步骤3: 发送重复起始 + 设备读地址 (0xED)
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_STA_SI);
I2C_WAIT_READY(I2C0);
I2C_SET_DATA(I2C0, 0xED); // 读地址
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI);
I2C_WAIT_READY(I2C0);
// 步骤4: 读取数据 (NACK + STOP)
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI | I2C_CTL_AA); // 先ACK使能
I2C_WAIT_READY(I2C0);
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_SI); // 读最后1字节时关闭ACK
I2C_WAIT_READY(I2C0);
id = I2C_GET_DATA(I2C0); // 获取ID
I2C_SET_CONTROL_REG(I2C0, I2C_CTL_STO_SI); // 发送STOP
return id;
}
4. 主函数调用
int main(void) {
SYS_Init(); // 系统初始化(时钟、GPIO等)
I2C0_Init(); // 初始化I2C0
uint8_t chipID = BME280_ReadChipID();
printf("BME280 Chip ID: 0x%Xn", chipID); // 预期输出0x60
while(1);
}
关键说明
- I2C地址:
如果开发板原理图显示SDO接地,则地址为 0x76(写0xEC/读0xED),否则用0x77。
- 错误处理:
添加超时检查(避免I2C总线锁死):
if (I2C_GET_TIMEOUT_FLAG(I2C0)) {
I2C_ClearTimeoutFlag(I2C0);
return 0xFF; // 错误码
}
- 调试工具:
使用逻辑分析仪检查I2C时序(START、地址、数据、STOP)。
替代方法:使用BSP库函数
uint8_t Read_ChipID(void) {
uint8_t reg = 0xD0; // 芯片ID寄存器
uint8_t id;
I2C_ReadByteOneReg(I2C0, 0x76, reg, &id); // 0x76为设备地址
return id;
}
通过以上步骤,即可正确读取BME280的芯片ID。