第32讲:实战——I2C传感器极简驱动快速验证
·
CSDN专栏:
第32讲:实战——I2C传感器极简驱动快速验证
一、I2C传感器驱动基础
I2C是最常用的传感器接口,快速验证I2C传感器驱动是嵌入式开发的基本功。
1.1 I2C传感器特点
优点:
- 只需两根线(SCL、SDA)
- 支持多设备共享总线
- 协议简单
常见I2C传感器:
- 温湿度:SHT30、BME280
- 加速度:MPU6050、LIS3DH
- 气压:BMP280
- 光照:BH1750
- 颜色:TCS34725
1.2 I2C驱动要点
基本操作:
- 写寄存器:发送设备地址+寄存器地址+数据
- 读寄存器:发送设备地址+寄存器地址,然后读取数据
时序要求:
- Start/Stop条件
- ACK/NACK应答
- 总线恢复时间
二、SHT30温湿度传感器
2.1 快速验证流程
Prompt:
生成STM32F103 SHT30驱动:
- I2C1:PB6(SCL)、PB7(SDA)
- 地址:0x44
- 功能:读取温度和湿度
- 使用HAL库
AI生成:
#include "stm32f1xx_hal.h"
I2C_HandleTypeDef hi2c1;
#define SHT30_ADDR 0x44
void I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
}
int8_t SHT30_Read(float *temperature, float *humidity) {
uint8_t cmd[2] = {0x2C, 0x06};
uint8_t data[6];
// 发送测量命令
if(HAL_I2C_Master_Transmit(&hi2c1, SHT30_ADDR << 1, cmd, 2, 100) != HAL_OK) {
return -1;
}
// 等待测量完成
HAL_Delay(20);
// 读取数据
if(HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR << 1, data, 6, 100) != HAL_OK) {
return -1;
}
// 计算温度
uint16_t rawTemp = (data[0] << 8) | data[1];
*temperature = -45.0f + 175.0f * (float)rawTemp / 65535.0f;
// 计算湿度
uint16_t rawHumi = (data[3] << 8) | data[4];
*humidity = 100.0f * (float)rawHumi / 65535.0f;
return 0;
}
int main(void) {
HAL_Init();
SystemClock_Config();
I2C1_Init();
UART_Init();
float temp, humi;
while(1) {
if(SHT30_Read(&temp, &humi) == 0) {
printf("Temperature: %.2f°C, Humidity: %.2f%%\r\n", temp, humi);
} else {
printf("SHT30 read failed\r\n");
}
HAL_Delay(1000);
}
}
2.2 验证方法
检查设备是否就绪:
void SHT30_Check(void) {
if(HAL_I2C_IsDeviceReady(&hi2c1, SHT30_ADDR << 1, 3, 100) == HAL_OK) {
printf("SHT30 found at 0x%02X\r\n", SHT30_ADDR);
} else {
printf("SHT30 not found\r\n");
}
}
I2C总线扫描:
void I2C_Scan(void) {
printf("I2C Scan:\r\n");
for(uint8_t addr = 0; addr < 128; addr++) {
if(HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 1, 10) == HAL_OK) {
printf("Device found at 0x%02X\r\n", addr);
}
}
}
三、MPU6050加速度传感器
3.1 MPU6050驱动
Prompt:
生成STM32F103 MPU6050驱动:
- I2C1:PB6(SCL)、PB7(SDA)
- 地址:0x68
- 功能:读取加速度和陀螺仪
- 使用HAL库
AI生成:
#define MPU6050_ADDR 0x68
int8_t MPU6050_Init(void) {
uint8_t data;
// 唤醒MPU6050
data = 0x00;
if(HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR << 1, 0x6B, 1, &data, 1, 100) != HAL_OK) {
return -1;
}
// 配置加速度量程(±2g)
data = 0x00;
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR << 1, 0x1C, 1, &data, 1, 100);
// 配置陀螺仪量程(±250°/s)
data = 0x00;
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR << 1, 0x1B, 1, &data, 1, 100);
return 0;
}
int8_t MPU6050_ReadAccel(float *ax, float *ay, float *az) {
uint8_t data[6];
if(HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR << 1, 0x3B, 1, data, 6, 100) != HAL_OK) {
return -1;
}
int16_t rawX = (data[0] << 8) | data[1];
int16_t rawY = (data[2] << 8) | data[3];
int16_t rawZ = (data[4] << 8) | data[5];
// 转换为g(±2g量程)
*ax = (float)rawX / 16384.0f;
*ay = (float)rawY / 16384.0f;
*az = (float)rawZ / 16384.0f;
return 0;
}
四、BME280环境传感器
4.1 BME280驱动
Prompt:
生成STM32F103 BME280驱动:
- I2C1:PB6(SCL)、PB7(SDA)
- 地址:0x76
- 功能:读取温度、湿度、气压
- 使用HAL库
AI生成核心代码:
#define BME280_ADDR 0x76
int8_t BME280_Init(void) {
uint8_t data;
// 检查芯片ID
if(HAL_I2C_Mem_Read(&hi2c1, BME280_ADDR << 1, 0xD0, 1, &data, 1, 100) != HAL_OK) {
return -1;
}
if(data != 0x60) { // BME280芯片ID
return -1;
}
// 配置湿度过采样(x1)
data = 0x01;
HAL_I2C_Mem_Write(&hi2c1, BME280_ADDR << 1, 0xF2, 1, &data, 1, 100);
// 配置温度和气压过采样、工作模式
data = 0x27; // 温度x1、气压x1、正常模式
HAL_I2C_Mem_Write(&hi2c1, BME280_ADDR << 1, 0xF4, 1, &data, 1, 100);
// 配置待机时间、滤波器
data = 0x00;
HAL_I2C_Mem_Write(&hi2c1, BME280_ADDR << 1, 0xF5, 1, &data, 1, 100);
return 0;
}
int8_t BME280_Read(float *temperature, float *pressure, float *humidity) {
uint8_t data[8];
// 读取所有数据
if(HAL_I2C_Mem_Read(&hi2c1, BME280_ADDR << 1, 0xF7, 1, data, 8, 100) != HAL_OK) {
return -1;
}
// 解析数据(简化版,实际需要补偿计算)
uint32_t rawPress = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
uint32_t rawTemp = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
uint16_t rawHumi = (data[6] << 8) | data[7];
// 简化计算(实际需要补偿)
*temperature = (float)rawTemp / 100.0f;
*pressure = (float)rawPress / 100.0f;
*humidity = (float)rawHumi / 1024.0f;
return 0;
}
五、I2C调试技巧
5.1 常见问题
问题一:设备未找到
原因:
- 设备地址错误
- I2C引脚配置错误
- 设备未供电
解决:
- I2C总线扫描
- 检查引脚配置
- 检查供电
问题二:读取数据错误
原因:
- 寄存器地址错误
- 时序问题
- 总线干扰
解决:
- 添加延时
- 降低I2C速率
- 检查寄存器地址
5.2 调试代码
I2C读取调试:
int8_t I2C_Read_Debug(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {
printf("I2C Read: Addr=0x%02X, Reg=0x%02X, Len=%d\r\n", addr, reg, len);
HAL_StatusTypeDef status = HAL_I2C_Mem_Read(&hi2c1, addr << 1, reg, 1, data, len, 100);
if(status == HAL_OK) {
printf("Data: ");
for(uint16_t i = 0; i < len; i++) {
printf("%02X ", data[i]);
}
printf("\r\n");
return 0;
} else {
printf("Error: %d\r\n", status);
return -1;
}
}
六、本讲核心要点
6.1 记住这三句话
-
I2C传感器驱动:写寄存器、读寄存器、数据转换
-
快速验证:设备扫描、读取数据、验证合理性
-
调试技巧:I2C扫描、读取调试、时序检查
6.2 实践建议
对于新手:
- 学习I2C协议
- 实践传感器驱动
- 使用调试技巧
对于有经验工程师:
- 建立传感器驱动模板库
- 实现通用I2C驱动框架
- 优化性能
6.3 下讲预告
第33讲将深入讲解:实战:ADC采集、电压采样快速代码生成
ADC是模拟量采集的基础,如何快速生成ADC采集代码?下一讲将详细讲解。
更多推荐


所有评论(0)