STM32F103硬件I2C驱动GZP6859D压力传感器

一、GZP6859D传感器概述

GZP6859D是一款高精度数字式压力传感器,采用I2C数字接口通信。主要特性:

  • 24位压力ADC输出
  • 16位温度ADC输出
  • 支持单次/连续测量模式
  • 工作电压:2.7V~5.5V

二、驱动设计解析

在STM32CUBEMX中已经配置好了I2C

2.1 寄存器定义(GZP6859D.h)参考芯片手册


#define GZP6859_K_VALUE          512

#define GZP6859_I2C_ADDR         0x6D  // I2C 地址

#define GZP6859_WRITE_BIT        0x00  // I2C 写操作标志位
#define GZP6859_READ_BIT         0x01  // I2C 读操作标志位

// 寄存器地址定义
#define GZP6859_DATA_MSB_ADDR    0x06  // 数据寄存器(MSB)
#define GZP6859_DATA_CSB_ADDR    0x07  // 数据寄存器(CSB)
#define GZP6859_DATA_LSB_ADDR    0x08  // 数据寄存器(LSB)
#define GZP6859_TEMP_MSB_ADDR    0x09  // 温度寄存器(MSB)
#define GZP6859_TEMP_LSB_ADDR    0x0A  // 温度寄存器(LSB)
#define GZP6859_CMD_ADDR         0x30  // 命令寄存器地址
#define GZP6859_SYS_CONFIG_ADDR  0xA5  // 系统配置寄存器地址
#define GZP6859_P_CONFIG_ADDR    0xA6  // 压力配置寄存器地址

// 定义 Sleep Time 位掩码,用于设置休眠模式下的时间间隔
#define GZP6859_SLEEP_TIME_MASK  (0x0F << 4)        // 睡眠时间掩码(4 位,移位4个位置)
#define GZP6859_SET_SLEEP_TIME(value)  ((value) << 4)  // 设置 Sleep Time,值为 4 位,表示时间间隔

// 定义 Measurement Control 工作模式掩码,3 位
#define GZP6859_MCTRL_MASK       (0x07)               // 3 位掩码,支持的工作模式:000-011
#define GZP6859_SET_MCTRL(value) ((value) & 0x07)      // 设置工作模式(0 到 3 之间的模式)

// 定义 SCO 位掩码,用于是否数据采集完成的标志
// 设置 SCO 位,表示数据采集是否完成,1 为开始采集,0 为采集结束(休眠工作模式除外)
#define GZP6859_SCO_MASK         (0x01 << 3)          // SCO 位,1 位掩码,表示是否持续采集数据
#define GZP6859_SET_SCO(value)   (((value) & 0x01) << 3)  // 设置 SCO 位,表示是否持续采集数据,1 为持续采集
#define GZP6859_SCO_START 0x01
#define GZP6859_SCO_END 0x00
// 组合命令:组合 Sleep Time、SCO 和 Measurement Control 设置
#define GZP6859_COMPOSE_CMD(Sleep_time, SCO, MCTRL) \
    (GZP6859_SET_SLEEP_TIME(Sleep_time) | GZP6859_SET_SCO(SCO) | GZP6859_SET_MCTRL(MCTRL))

// 工作模式命令宏
#define GZP6859_CMD_SINGLE_TEMP_MODE    GZP6859_COMPOSE_CMD(0, 1, 0)  // 单次温度采集模式(MCTRL = 000)
#define GZP6859_CMD_SINGLE_PRESS_MODE   GZP6859_COMPOSE_CMD(0, 1, 1)  // 单次压力采集模式(MCTRL = 001)
#define GZP6859_CMD_COMBINED_MODE       GZP6859_COMPOSE_CMD(0, 1, 2)  // 组合采集模式(MCTRL = 010)
#define GZP6859_CMD_SLEEP_MODE(Sleep_time)  GZP6859_COMPOSE_CMD(Sleep_time, 1, 3)  // 休眠模式(MCTRL = 011),需要传入 Sleep_time

// 注释解释:
// - GZP6859_CMD_SINGLE_TEMP_MODE:单次温度采集模式,采集一次温度数据,MCTRL=000,SCO=1。
// - GZP6859_CMD_SINGLE_PRESS_MODE:单次压力采集模式,采集一次压力数据,MCTRL=001,SCO=1。
// - GZP6859_CMD_COMBINED_MODE:组合采集模式,先采集一次温度数据,再采集一次压力数据,MCTRL=010,SCO=1。
// - GZP6859_CMD_SLEEP_MODE:休眠模式,定期进行一次组合采集,SCO=1,MCTRL=011,Sleep_time 用来设置采集间隔(62.5ms 到 1s),间隔值由 Sleep_time 决定。
// Sleep_time 参数:
// 0000 = 无效(不使用)
// 0001 = 62.5ms
// 0010 = 125ms
// 0100 = 500ms
// 1111 = 1s
// 定义返回错误代码
#define GZP6859_READ_SUCCESS           0   // 读取成功
#define GZP6859_READ_ERROR             1   // 一般读取错误
#define GZP6859_READ_REG_ERROR         2   // 寄存器读取错误

2.2 核心数据结构

typedef struct {
    int32_t raw_pressure_ad;     // 24位原始AD值
    int32_t pressure_pa;         // 转换后的压力值(Pa)
    uint8_t raw_press_data[3];   // 原始寄存器数据
} PressureData;

typedef struct {
    int16_t raw_temperature_ad;  // 16位温度AD值
    int16_t temperature_celsius; // 转换后的温度值
    uint8_t raw_temp_data[2];    // 原始温度寄存器数据
} TemperatureData;

2.3 基础通信函数

2.3.1 寄存器读写

HAL_StatusTypeDef GZP6859_ReadReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data, uint8_t length) {
    return HAL_I2C_Mem_Read(hi2c,            // I2C 接口句柄
                            (GZP6859_I2C_ADDR << 1) | GZP6859_READ_BIT, // GZP6859 的设备地址,左移一位以符合 I2C 7 位地址协议,加上读标志位
                            reg,                // 要读取的寄存器地址
                            I2C_MEMADD_SIZE_8BIT, // 寄存器地址的大小为 8 位
                            data,               // 数据存储指针
                            length,             // 数据长度
                            10                  // 超时时间(单位:ms,这里设置为 10ms)
                           );
}

/**
  * @brief  向 GZP6859 设备写入寄存器数据
  * @param  hi2c      指向 I2C 接口句柄的指针
  * @param  reg       要写入的寄存器地址
  * @param  data      要写入的数据指针
  * @param  length    要写入的数据长度(字节数)
  * @retval HAL_StatusTypeDef HAL_I2C_Mem_Write 的返回状态
  */
HAL_StatusTypeDef GZP6859_WriteReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data, uint8_t length) {
    return HAL_I2C_Mem_Write(hi2c,            // I2C 接口句柄
                             (GZP6859_I2C_ADDR << 1) | GZP6859_WRITE_BIT, // GZP6859 的设备地址,左移一位以符合 I2C 7 位地址协议,加上写标志位
                             reg,                // 要写入的寄存器地址
                             I2C_MEMADD_SIZE_8BIT, // 寄存器地址的大小为 8 位
                             data,               // 要写入的数据指针
                             length,             // 数据长度
                             10                  // 超时时间(单位:ms,这里设置为 10ms)
                            );
}

2.4 数据采集流程

2.4.1 压力数据读取

uint8_t GZP6859_ReadPress(I2C_HandleTypeDef *hi2c, PressureData *pressureData)
{
    // 读取三个字节的原始数据
    HAL_StatusTypeDef status;
    status |= GZP6859_ReadReg(hi2c, GZP6859_DATA_MSB_ADDR, 
                             pressureData->raw_press_data, 3);
    
    // 组合24位AD值
    pressureData->raw_pressure_ad = (pressureData->raw_press_data[0] << 16)
                                  | (pressureData->raw_press_data[1] << 8)
                                  | pressureData->raw_press_data[2];
    
    // 补码转换
    if(pressureData->raw_pressure_ad > 0x7FFFFF)
        pressureData->raw_pressure_ad -= 16777216;
    
    // 转换为Pa值
    pressureData->pressure_pa = pressureData->raw_pressure_ad / GZP6859_K_VALUE;
    
    return (status == HAL_OK) ? GZP6859_READ_SUCCESS : GZP6859_READ_ERROR;
}

三、工作模式配置

3.1 模式设置函数

void GZP6859_Set_SinglePress_Mode(I2C_HandleTypeDef *hi2c)
{
    uint8_t cmd = GZP6859_CMD_SINGLE_PRESS_MODE;
    GZP6859_WriteReg(hi2c, GZP6859_CMD_ADDR, &cmd, 1);
}

3.2 状态检测

uint8_t GZP6859_SCO_Status(I2C_HandleTypeDef *hi2c)
{
    uint8_t status;
    GZP6859_ReadReg(hi2c, GZP6859_CMD_ADDR, &status, 1);
    return (status >> 3) & 0x01; // 提取SCO位
}

四、本次测试

// ============================================================================
// @brief   GZP6859_Test1_init 函数初始化(主程序中调用该测试例程时先调用该函数)
// @details 初始化 GZP6859 传感器的组合模式,并读取初始温度数据。
//          该初始化过程是后续单次压力测量的基础。
// ============================================================================
void GZP6859_Test1_init(void){
    
    // 初始化 GZP6859 传感器的组合测量模式
    // 组合模式将同时测量温度和压力,为后续单次压力测量提供参考数据
    GZP6859_Set_Combine_Mode(&hi2c1);

    // 检查传感器配置状态,确保组合模式设置成功
    // 如果状态异常,可能需要重新配置传感器
    GZP6859_SCO_Status(&hi2c1);
    
    // 以下代码被注释,可能用于调试或未来功能扩展
    // 压力数据和温度数据的相关操作暂未启用
    // 如果需要恢复这些功能,请取消注释并确保相关数据结构已正确定义
    
    // PressureData pressureData;
    // TemperatureData tempData;
    
    // // 读取温度数据
    // GZP6859_ReadTemp(&hi2c1, &tempData);
    
    // // 发送原始温度数据(2 字节)
    // RS485_SendData(tempData.raw_temp_data, 2);

    // // 发送转换后的温度数据(2 字节)
    // RS485_SendData(tempData.temperature_bytes, 2);       
    
    // // 读取压力数据
    // GZP6859_ReadPress(&hi2c1, &pressureData);
    
    // // 发送原始压力数据(3 字节)
    // RS485_SendData(pressureData.raw_press_data, 3);
    
    // // 发送转换后的压力数据(4 字节,单位为 Pa)
    // RS485_SendData(pressureData.pressure_pa_bytes, 4);
}
// ============================================================================
// @brief   GZP6859_Test1 函数(调用该测试例程时运行该函数,该函数循环运行,一般会卡在这个例程的循环中)
// @details 使用 GZP6859 传感器在单次压力测量模式下读取压力数据,并通过 RS485 发送。
//          该函数假设 `GZP6859_Test1_init` 已先调用,完成必要的初始化工作。
// ============================================================================
void GZP6859_Test1(void){
    
    // 创建一个 PressureData 对象,用于存储压力测量结果
    PressureData pressureData;
    
    // 设置 GZP6859 传感器为单次压力测量模式
    // 该模式将只测量压力,温度数据使用之前组合模式读取的值
    GZP6859_Set_SinglePress_Mode(&hi2c1);
    
    // 检查传感器配置状态,确保单次压力测量模式设置成功
    // 如果状态异常,可能需要重新配置传感器
    GZP6859_SCO_Status(&hi2c1);
    
    // 以下代码被注释,可能用于调试温度数据或未来功能扩展
    // 如果需要恢复这些功能,请取消注释并确保相关数据结构已正确定义
    
    // TemperatureData tempData;
    
    // // 设置温度单次测量模式
    // GZP6859_Set_SingleTemp_Mode(&hi2c1);
    
    // // 检查传感器配置状态
    // GZP6859_SCO_Status(&hi2c1);
    
    // // 读取温度数据
    // GZP6859_ReadTemp(&hi2c1, &tempData);
    
    // // 发送原始温度数据(2 字节)
    // RS485_SendData(tempData.raw_temp_data, 2);
    
    // // 发送转换后的温度数据(2 字节)
    // RS485_SendData(tempData.temperature_bytes, 2);    
        
    // 读取压力数据
    GZP6859_ReadPress(&hi2c1, &pressureData);
    
    // 发送转换后的压力数据(4 字节,单位为 Pa)
    // 该数据可用于后续的压力计算或显示
    RS485_SendData(pressureData.pressure_pa_bytes, 4);    
    
    // // 发送原始压力数据(3 字节)
    // RS485_SendData(pressureData.raw_press_data, 3);
}

五、开发注意事项

  1. 时序控制要点:

    • 模式切换后需等待至少5ms
    • 连续测量间隔建议≥50ms
    • SCO位为0表示数据就绪
  2. 精度校准建议:

    // 在已知压力环境下进行校准
    #define CALIB_OFFSET   -123  // 校准偏移量
    pressure_pa = (raw_pressure_ad / GZP6859_K_VALUE) + CALIB_OFFSET;
    
  3. 异常处理策略:

    • 连续3次读取失败触发硬件复位
    • AD值超范围时启动自检程序

结语

实际开发中可根据需求调整:

  1. 增加IIR数字滤波器平滑数据
  2. 实现自动量程切换功能
  3. 添加EEPROM校准参数存储
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值