【STM32】RTT-Studio中HAL库开发教程六:IIC通信--GZP6877D气压传感器

2024-08-26 22:52

本文主要是介绍【STM32】RTT-Studio中HAL库开发教程六:IIC通信--GZP6877D气压传感器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 一、简介
    • 二、寄存器操作
    • 三、硬件IIC通信
    • 四、模拟IIC通信
    • 五、测试验证

一、简介

  GZP6877D 型压力传感器采用 SOP6 封装形式,倒钩管的设计可以保证安装的密封性。内有封装的压力传感器与信号调理芯片,对传感器的偏移、灵敏度、温漂和非线性进行数字补偿。采用 24 位 ADC,并且调理芯片内置温度传感器,可以输出高精度的压力值和温度值。同时提供 IIC 通讯协议接口,抗干扰能力强。所有测量数据都经过充分校准和温度补偿。

  • 测量范围-100kPa…0~0.5kPa…1000kPa
  • 表压型、气嘴带防脱结构
  • 电源电压: 2.5V~5.5V
  • 适用于无腐蚀性的气体
  • IIC 输出

  I2C 总线使用 SCL 和 SDA 作为信号线,这两根线都通过上拉电阻(典型值 4.7K)连接到 VDD,不通信时都保持为高电平。I2C 设备地址为 0x6D。
  GZP6877D芯片数据手册:https://atta.szlcsc.com/upload/public/pdf


二、寄存器操作

1.寄存器描述
(1)Reg0x06—Reg0x08:压力数据寄存器

(2)Reg0x09—Reg0x0A:温度数据寄存器

(3)Reg0x30:测量命令寄存器
  Bit:<2:0>
   000:单次温度采集模式。
   001:单次传感器压力信号采集模式。(使用此模式之前需要先读取温度,以获取温度校准系数,否则读数不准)
   010:组合采集模式(一次温度采集后立即进行一次传感器压力信号采集)。
   011,休眠工作模式(定期的执行一次组合采集模式,间隔时间由‘sleep_time’决定)
  Sco:<3>:数据采集完成标志位。1–开始数据采集;0–采集结束(休眠工作模式除外)。
  Sleep_time<7:4>:0001:62.5ms, 0010:125ms … 1111: 1s, 0000:无意义。(仅在休眠工作模式下有效)

(4)Reg0xA5:
  Aout_config<7:4>:模拟输出配置(建议保留默认配置)
  LDO_config:内部 LDO 配置。0,配置成 1.8V;1,配置成 3.6V
  Unipolar:0,ADC 原始数据以有符号数格式输出;1: ADC 原始数据以无符号格式输出。
  Data_out_control:0,输出校准数据;1,输出 ADC 原始数据(默认配置为 0)
  Diag_on:0,关闭诊断功能;1,开启诊断功能(默认开启)

(5)Reg0xA6
  Input Swap:在传感器内部交换差分信号极性。
  Gain_P<5:3>:采集传感器信号时 PGA 增益,000:增益=1X。001:增益=2X。010:增益=4X。011:增益=8X。100: 增益=16X。101:增益=32X。110: 增益=64X。111:增益=128X。
  OSR_P<2:0>:采集传感器信号时的过采样,000:1024X, 001:2048X, 010:4096X, 011:8192X,100:256X, 101:512X,110:16384X, 111:32768X。
在这里插入图片描述

2.工作模式说明
(1)组合数据采集模式:设置‘measurement_control’=010 和‘sco’=1 进入组合数据采集模式。
  芯片上电后先后进行一次温度数据采集和一次传感器数据采集,完成后回到待机模式,并自动将‘sco’置 0。在组合采集模式下,“Data_out_control”寄存器必须设置为 0,校准后的温度数据储存在 0x09~0x0A 寄存器,压力数据储存在 0x06~0x08 寄存器。

组合模式读取数据按照如下指令顺序进行操作:

  • 发送指令 0x0A 到 0x30 寄存器进行一次温度采集,一次压力数据采集。
  • 读取 0x30 寄存器地址,若Sco位为0代表采集结束,可以读取数据。或等待延迟10ms。
  • 读取 0x06、0x07、0x08 三个寄存器地址数据构成 24 位 AD 值(压力数据 AD 值),读取 0x09、0x0A 两个寄存器地址数据构成 16 位 AD 值(温度数据 AD 值)
  • 按以下公式换算成实际压力、温度值。

(2)休眠数据采集模式
  设置‘measurement_control’=011 和‘sco’=1 进入休眠数据采集模式。芯片上电后,以一定的时间间隔进行一次温度数据采集和一次传感器数据采集,间隔时间由’sleep_time’ 设置,范围为 62.5ms 到 1s。除非手动将‘sco’置 0,不然不会停止采集。在休眠数据采集模式下‘Data_out_control’必须设置为 0,校准后的温度数据储存在 0x09~0x0A 寄存器,压力数据储存在 0x06~0x08 寄存器。

3.温度和压力值换算公式
(1)最高位为“0”代表正压/正温度:
  压力:Pressure = Pressure_ ADC / k
  温度:Temperature = Temp_ ADC / 256

(2)最高位为“1”代表负压/负温度:
  压力:Pressure = (Pressure_ADC - 16777216) / k
  温度:Temperature = (Temp_ADC - 65536) / 256

PS:传感器校准后的输出可视为当前实际压力值(±1%Span);传感器校准后的输出:单位 Pa(默认),若要显示其他单位,可在换算公式里输入相应的系数进行换算;
关于上述压力 ADC 换算公式中 k 值的选取可参照下表:
在这里插入图片描述
  量程 P 为测量区间的最大值,比如,测量-30~80kpa,P=80kpa,k 值为 64。


三、硬件IIC通信

一般硬件IIC的通信速率更快,更简单,大部分可以选择使用硬件IIC,如果由于硬件IIC不够使用,可以使用软件IIC进行替代。

1.初始化配置
(1)需要先打开图形界面配置的I2C驱动:
在这里插入图片描述

(2)在board.h中添加一下代码进行初始化。

/** if you want to use i2c bus(soft simulate) you can use the following instructions.** STEP 1, open i2c driver framework(soft simulate) support in the RT-Thread Settings file** STEP 2, define macro related to the i2c bus*                 such as     #define BSP_USING_I2C1** STEP 3, according to the corresponding pin of i2c port, modify the related i2c port and pin information*                 such as     #define BSP_I2C1_SCL_PIN    GET_PIN(port, pin)   ->   GET_PIN(C, 11)*                             #define BSP_I2C1_SDA_PIN    GET_PIN(port, pin)   ->   GET_PIN(C, 12)*//*#define BSP_USING_I2C1*/
#ifdef BSP_USING_I2C1
#define BSP_I2C1_SCL_PIN    GET_PIN(port, pin)
#define BSP_I2C1_SDA_PIN    GET_PIN(port, pin)
#endif#define BSP_USING_I2C2
#ifdef BSP_USING_I2C2
#define BSP_I2C2_SCL_PIN    GET_PIN(F, 1)
#define BSP_I2C2_SDA_PIN    GET_PIN(F, 0)
#endif

(3)在board.c中添加:void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)来初始化IIC。

void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if (hi2c->Instance == I2C2){__HAL_RCC_GPIOF_CLK_ENABLE();/**I2C2 GPIO ConfigurationPF0     ------> I2C2_SDAPF1     ------> I2C2_SCL*/GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);/* Peripheral clock enable */__HAL_RCC_I2C2_CLK_ENABLE();}
}

(4)在是他们2fxxx_hal_conf.h中添加如下的宏定义
在这里插入图片描述

(5)GZP6877.h文件

#ifndef APPLICATIONS_GZP6877_H_
#define APPLICATIONS_GZP6877_H_#include <drv_common.h>
#include <stdio.h>/**====================================================###### 宏定义 ######==================================================*/
#define GZP6877_WRITE_BIT           0x00        // 硬件I2C写标志
#define GZP6877_READ_BIT            0x01        // 硬件I2C读标志#define GZP6877_SLAVE_ADDR          0x6D        // 设备地址
#define GZP6877_WRITE_ADDR          ((GZP6877_SLAVE_ADDR << 1) | GZP6877_WRITE_BIT)
#define GZP6877_READ_ADDR           ((GZP6877_SLAVE_ADDR << 1) | GZP6877_READ_BIT)#define GZP6877_DATA_MSB_ADDR       0x06        // 气压高地址
#define GZP6877_DATA_CSB_ADDR       0x07        // 气压中地址
#define GZP6877_DATA_LSB_ADDR       0x08        // 气压低地址
#define GZP6877_TEMP_MSB_ADDR       0x09        // 温度高地址
#define GZP6877_TEMP_LSB_ADDR       0x0A        // 温度低地址
#define GZP6877_CMD_ADDR            0x30        // 测量命令寄存器#define GZP6877_ONE_TEMP_CMD        0x08        // 单次温度采集模式
#define GZP6877_ONE_PRESS_CMD       0x09        // 单次采集传感器压力信号
#define GZP6877_COMBINED_COM        0x0A        // 组合采集模式#define GZP6877_PRE_LIMIT           8388606     // 气压界限
#define GZP6877_PRE_ADJUST          16777216    // 气压校准值
#define GZP6877_K_VALUE             8           // 气压K值
#define GZP6877_TEMP_LIMIT          32768       // 温度界限
#define GZP6877_TEMP_ADJUST         65536       // 温度校准值
#define GZP6877_TEMP_K              256         // 温度K值I2C_HandleTypeDef hi2c2;extern void GZP6877_I2C2_Init(void);
extern void GZP6859D_ReadSingleModePressureData(uint32_t *pPressure);
extern void GZP6859D_ReadSingleModeTempData(float *pTemperature);
extern void GZP6859D_ReadCombinedModeData(float *pTemperature, uint32_t *pPressure);
/**====================================================#######  END  #######=================================================*/#endif /* APPLICATIONS_GZP6877_H_ */

(6)GZP6877.c文件

#include "GZP6877.h"/*** @breif GZP6877的I2C初始化*/
void GZP6877_I2C2_Init(void)
{hi2c2.Instance = I2C2;hi2c2.Init.ClockSpeed = 100000;hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c2.Init.OwnAddress1 = 0;hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c2.Init.OwnAddress2 = 0;hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c2) != HAL_OK){Error_Handler();}
}/*** @brief 单次模式读取压力数据* @param pPressure -[out] 压力值,单位为Pa*/
void GZP6859D_ReadSingleModePressureData(uint32_t *pPressure)
{uint8_t cmd = GZP6877_ONE_PRESS_CMD;uint8_t result = 0;uint8_t pressArr[3] = {0};uint32_t press = 0;// 进行单次传感器压力信号采集模式HAL_I2C_Mem_Write(&hi2c2, GZP6877_WRITE_ADDR, GZP6877_CMD_ADDR, I2C_MEMADD_SIZE_8BIT, &cmd, 1, 10);// 采集结束HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_CMD_ADDR, I2C_MEMADD_SIZE_8BIT, &result, 1, 10);rt_kprintf("result:0x%02X  ", result);// 获取压力数据AD值HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_DATA_MSB_ADDR, I2C_MEMADD_SIZE_8BIT, &pressArr[0], 1, 10);rt_kprintf("0x%02X  ", pressArr[0]);HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_DATA_CSB_ADDR, I2C_MEMADD_SIZE_8BIT, &pressArr[1], 1, 10);rt_kprintf("0x%02X  ", pressArr[1]);HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_DATA_LSB_ADDR, I2C_MEMADD_SIZE_8BIT, &pressArr[2], 1, 10);rt_kprintf("0x%02X  ", pressArr[2]);// 压力计算公式press = ((pressArr[0] << 16) + (pressArr[1] << 8) + pressArr[2]);if (press > GZP6877_PRE_LIMIT){press = press - GZP6877_PRE_ADJUST;}// 单位为Papress = press / GZP6877_K_VALUE;*pPressure = press;rt_kprintf("press:%d Pa\r\n", press);
}/*** @brief 单次模式读取温度数据* @param pTemperature -[out] 温度值,单位为℃*/
void GZP6859D_ReadSingleModeTempData(float *pTemperature)
{uint8_t cmd = GZP6877_ONE_TEMP_CMD;uint8_t result = 0;uint8_t tempArr[3] = {0};float temp = 0;// 进行单次传感器温度信号采集模式HAL_I2C_Mem_Write(&hi2c2, GZP6877_WRITE_ADDR, GZP6877_CMD_ADDR, I2C_MEMADD_SIZE_8BIT, &cmd, 1, 10);// 采集结束HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_CMD_ADDR, I2C_MEMADD_SIZE_8BIT, &result, 1, 10);rt_kprintf("result:0x%02X  ", result);// 获取温度数据AD值HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_TEMP_MSB_ADDR, I2C_MEMADD_SIZE_8BIT, &tempArr[0], 1, 10);rt_kprintf("0x%02X  ", tempArr[0]);HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_TEMP_LSB_ADDR, I2C_MEMADD_SIZE_8BIT, &tempArr[1], 1, 10);rt_kprintf("0x%02X  ", tempArr[1]);// 温度计算公式temp = ((tempArr[0] << 8) + tempArr[1]);if (temp > GZP6877_TEMP_LIMIT){temp = temp - GZP6877_TEMP_ADJUST;}// 单位为℃temp = temp / GZP6877_TEMP_K;*pTemperature = temp;printf("temp:%.2f C\r\n", temp);
}/*** @brief 组合模式读取数据* @param pTemperature -[out] 温度值* @param pPressure -[out] 压力值*/
void GZP6859D_ReadCombinedModeData(float *pTemperature, uint32_t *pPressure)
{uint8_t cmd = GZP6877_COMBINED_COM;uint8_t result = 0;uint8_t tempArr[4] = {0};float temp = 0;uint8_t pressArr[4] = {0};uint32_t press = 0;// 进行组合模式读取数据HAL_I2C_Mem_Write(&hi2c2, GZP6877_WRITE_ADDR, GZP6877_SLAVE_ADDR, I2C_MEMADD_SIZE_8BIT, &cmd, 1, 10);// 采集结束HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_SLAVE_ADDR, I2C_MEMADD_SIZE_8BIT, &result, 1, 10);rt_kprintf("0x%02X  ", result);// 获取温度数据AD值HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_TEMP_MSB_ADDR, I2C_MEMADD_SIZE_8BIT, &tempArr[0], 1, 10);rt_kprintf("0x%02X  ", tempArr[0]);HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_TEMP_LSB_ADDR, I2C_MEMADD_SIZE_8BIT, &tempArr[1], 1, 10);rt_kprintf("0x%02X  ", tempArr[1]);// 温度计算公式temp = ((tempArr[0] << 8) + tempArr[1]);if (temp > GZP6877_TEMP_LIMIT){temp = temp - GZP6877_TEMP_ADJUST;}// 单位为℃temp = temp / GZP6877_TEMP_K;*pTemperature = temp;printf("temp:%.2f C\r\n", temp);// 获取压力数据AD值HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_DATA_MSB_ADDR, I2C_MEMADD_SIZE_8BIT, &pressArr[0], 1, 10);rt_kprintf("0x%02X  ", pressArr[0]);HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_DATA_CSB_ADDR, I2C_MEMADD_SIZE_8BIT, &pressArr[1], 1, 10);rt_kprintf("0x%02X  ", pressArr[1]);HAL_I2C_Mem_Read(&hi2c2, GZP6877_READ_ADDR, GZP6877_DATA_LSB_ADDR, I2C_MEMADD_SIZE_8BIT, &pressArr[2], 1, 10);rt_kprintf("0x%02X  ", pressArr[2]);// 压力计算公式press = ((pressArr[0] << 16) + (pressArr[1] << 8) + pressArr[2]);if (press > GZP6877_PRE_LIMIT){press = press - GZP6877_PRE_ADJUST;}// 单位为Papress = press / GZP6877_K_VALUE;*pPressure = press;rt_kprintf("press:%d Pa\r\n", press);
}

(7)main.c

#include <rtthread.h>
#include <drv_common.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "GZP6877.h"int main(void)
{int count = 1;GZP6877_I2C2_Init();float temperature;uint32_t pressure;GZP6859D_ReadCombinedModeData(&temperature, &pressure);  //先以组合模式读取温度,以获取温度校准系数,否则读数不准while (count){GZP6859D_ReadSingleModePressureData(&pressure);GZP6859D_ReadSingleModeTempData(&temperature);printf("P:%d Pa T:%.2f C\r\n", pressure, temperature);rt_thread_mdelay(1000);}return RT_EOK;
}

四、模拟IIC通信

1.gzp6877.c文件

#include "gzp6877d.h"/*======================================================### 静态函数调用 ###==================================================*/
/*** @brief IIC的us延时函数* @param us: 延时时间*/
static void IIC_Delay_us(rt_uint32_t us)
{rt_hw_us_delay(us);
}/*** @brief IIC的起始信号*/
static void IIC_Start(void)
{GZP6877_SDA_OUT_MODE;GZP6877_SDA_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SDA_LOW;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);
}/*** @brief IIC的停止信号*/
static void IIC_Stop(void)
{GZP6877_SDA_OUT_MODE;GZP6877_SDA_LOW;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SDA_HIGH;IIC_Delay_us(IIC_DELAY_TIME);
}/*** @brief  IIC等待应答* @return 1:等待超时   0:得到应答*/
static uint8_t IIC_Wait_ACK(void)
{uint8_t outTime = 0;GZP6877_SDA_INPUT_MODE;GZP6877_SDA_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME);while (rt_pin_read(GZP6877_SDA_PIN)){outTime++;if (outTime >= ACK_OUT_TIME){IIC_Stop();return RT_ERROR;}}GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);return RT_EOK;
}/*** @brief 没有超时时间的应答函数*/
void IIC_ACK(void)
{GZP6877_SCL_LOW;GZP6877_SDA_OUT_MODE;GZP6877_SDA_LOW;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SDA_HIGH;IIC_Delay_us(IIC_DELAY_TIME);
}/*** @brief IIC无应答*/
void IIC_NACK(void)
{GZP6877_SCL_LOW;GZP6877_SDA_OUT_MODE;GZP6877_SDA_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);
}/*** @brief IIC发送一个字节数据*/
static void IIC_Send_Byte(uint8_t data)
{GZP6877_SDA_OUT_MODE;GZP6877_SCL_LOW;for (int i = 0; i < 8; ++i){if (data & (0x01 << (7 - i))){GZP6877_SDA_HIGH;}else{GZP6877_SDA_LOW;}IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);}GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SDA_HIGH;IIC_Delay_us(IIC_DELAY_TIME);
}/*** @brief 接收一个字节的数据* @return 返回接收到的数据*/
static uint8_t IIC_Read_Byte(void)
{uint8_t recv = 0;GZP6877_SDA_INPUT_MODE;for (int i = 0; i < 8; ++i){GZP6877_SCL_LOW;IIC_Delay_us(IIC_DELAY_TIME);GZP6877_SCL_HIGH;IIC_Delay_us(IIC_DELAY_TIME / 2);recv <<= 1;if (rt_pin_read(GZP6877_SDA_PIN)){recv++;}IIC_Delay_us(IIC_DELAY_TIME / 2);}GZP6877_SDA_HIGH;return recv;
}/*** @brief GZP6877写入一个字节的数据* @return 1: 异常     0:读取正常*/
static uint8_t GZP6877_Write_One_Byte(uint8_t address, uint8_t data)
{uint8_t ack;IIC_Start();IIC_Send_Byte(GZP6877_WRITE_ADDR);ack = IIC_Wait_ACK();if (ack == RT_ERROR){return RT_ERROR;}IIC_Send_Byte(address);ack = IIC_Wait_ACK();if (ack == RT_ERROR){return RT_ERROR;}IIC_Send_Byte(data);IIC_Wait_ACK();if (ack == RT_ERROR){return RT_ERROR;}IIC_Stop();return RT_EOK;
}/*** @brief GZP6877读一个字节的数据* @param address:读书数据的地址* @return 0:应答错误*/
static uint8_t GZP6877_Read_One_Byte(uint8_t address)
{uint8_t data, ack;IIC_Start();IIC_Send_Byte(GZP6877_WRITE_ADDR);ack = IIC_Wait_ACK();if (ack != RT_EOK){return 0;}IIC_Send_Byte(address);ack = IIC_Wait_ACK();if (ack != RT_EOK){return 0;}IIC_Start();IIC_Send_Byte(GZP6877_READ_ADDR);ack = IIC_Wait_ACK();if (ack != RT_EOK){return 0;}data = IIC_Read_Byte();IIC_Stop();return data;
}
/*=====================================================#######  END  #######=================================================*//*======================================================##### 外部调用 #####==================================================*/
/*** @brief IIC的GPIO引脚初始化*/
void GZP6877_GPIO_Init(void)
{GZP6877_SDA_OUT_MODE;GZP6877_SCL_OUT_MODE;GZP6877_SDA_HIGH;GZP6877_SCL_HIGH;
}/*** @brief GZP6877模块等待可读压力和温度* @return 0:可读  1:不可读*/
uint8_t GZP6877_Wait(void)
{uint8_t ack, data, status;ack = GZP6877_Write_One_Byte(GZP6877_CMD_ADDR, GZP6877_COM);if (ack){return RT_ERROR;}data = GZP6877_Read_One_Byte(GZP6877_CMD_ADDR);if (!data){return RT_ERROR;}status = data & 0x08;if (status){rt_thread_delay(20);}return 0;
}/*** @brief GZP6877模块读取压力* @return 返回气压值*/
int GZP6877_Read_Pressure(void)
{int pressure = 0;uint8_t pressure_H, pressure_M, pressure_L;pressure_H = GZP6877_Read_One_Byte(GZP6877_DATA_HSB_ADDR);pressure_M = GZP6877_Read_One_Byte(GZP6877_DATA_MSB_ADDR);pressure_L = GZP6877_Read_One_Byte(GZP6877_DATA_LSB_ADDR);pressure |= (int)pressure_H << 16;pressure |= (int)pressure_M << 8;pressure |= (int)pressure_L << 0;/* 超过 8388606(0x800000) 为负压值 */if (pressure > GZP6877_PRE_LIMIT){pressure = (pressure - GZP6877_PRE_ADJUST) / GZP6877_PRE_K;}else{pressure /= GZP6877_PRE_K;}return pressure;
}/*** @brief GZP6877模块读取温度* @return 返回温度值*/
float GZP6877_Read_Temperature(void)
{uint8_t temp_H, temp_L;float temp = 0;temp_H = GZP6877_Read_One_Byte(GZP6877_TEMP_MSB_ADDR);temp_L = GZP6877_Read_One_Byte(GZP6877_TEMP_LSB_ADDR);temp = (float)(temp_H << 8) + (float)(temp_L << 0);if (temp > GZP6877_TEMP_LIMIT){temp = (temp - GZP6877_TEMP_ADJUST) / GZP6877_TEMP_K;}else{temp /= GZP6877_TEMP_K;}return temp;
}/*** @brief 打印气压和温度*/
void GZP6877_Read_Data(void)
{int pres = 0;float temp = 0;pres = GZP6877_Read_Pressure();temp = GZP6877_Read_Temperature();printf("pres: %d Pa,  temp: %.3f C\n", pres, temp);
}
/*=====================================================#######  END  #######=================================================*/

2.gzp6877.h文件

#ifndef APPLICATIONS_GZP6877D_H_
#define APPLICATIONS_GZP6877D_H_#include <rtthread.h>
#include <drv_common.h>/**=====================================================###### 宏定义 ######==================================================*/
#define GZP6877_WRITE_BIT       0x00            // 硬件I2C写标志
#define GZP6877_READ_BIT        0x01            // 硬件I2C读标志#define GZP6877_SLAVE_ADDR      0x6D            // 设备地址
#define GZP6877_WRITE_ADDR      ((GZP6877_SLAVE_ADDR << 1) | GZP6877_WRITE_BIT)
#define GZP6877_READ_ADDR       ((GZP6877_SLAVE_ADDR << 1) | GZP6877_READ_BIT)#define GZP6877_COM             0x0A            // 测量一次数据指令
#define GZP6877_DATA_HSB_ADDR   0x06            // 气压高地址
#define GZP6877_DATA_MSB_ADDR   0x07            // 气压中地址
#define GZP6877_DATA_LSB_ADDR   0x08            // 气压低地址
#define GZP6877_TEMP_MSB_ADDR   0x09            // 温度高地址
#define GZP6877_TEMP_LSB_ADDR   0x0A            // 温度低地址
#define GZP6877_CMD_ADDR        0x30            // 测量命令寄存器#define GZP6877_PRE_LIMIT       8388606         // 气压界限
#define GZP6877_PRE_ADJUST      16777216        // 气压校准值
#define GZP6877_PRE_K           8               // 气压K值
#define GZP6877_TEMP_LIMIT      32786           // 温度界限
#define GZP6877_TEMP_ADJUST     65536           // 温度校准值
#define GZP6877_TEMP_K          256             // 温度K值#define IIC_DELAY_TIME          60              // IIC延时时间
#define ACK_OUT_TIME            250             // 应答信号超时时间#define GZP6877_SDA_PIN         GET_PIN(F, 0)   // PF0数据总线
#define GZP6877_SCL_PIN         GET_PIN(F, 1)   // PF1时钟总线#define GZP6877_SCL_OUT_MODE    rt_pin_mode(GZP6877_SCL_PIN, PIN_MODE_OUTPUT);  // SCL输出模式#define GZP6877_SDA_OUT_MODE    rt_pin_mode(GZP6877_SDA_PIN, PIN_MODE_OUTPUT);  // SDA输出模式
#define GZP6877_SDA_INPUT_MODE  rt_pin_mode(GZP6877_SDA_PIN, PIN_MODE_INPUT);   // SDA输出模式#define GZP6877_SDA_HIGH        rt_pin_write(GZP6877_SDA_PIN, PIN_HIGH);        // 设置SDA为高
#define GZP6877_SDA_LOW         rt_pin_write(GZP6877_SDA_PIN, PIN_LOW);         // 设置SDA为高#define GZP6877_SCL_HIGH        rt_pin_write(GZP6877_SCL_PIN, PIN_HIGH);        // 设置SCL为高
#define GZP6877_SCL_LOW         rt_pin_write(GZP6877_SCL_PIN, PIN_LOW);         // 设置SCL为高
/**====================================================#######  END  #######=================================================*//**==================================================##### 函数及变量声明 #####===============================================*/
extern void GZP6877_GPIO_Init(void);                // IIC的GPIO引脚初始化
extern uint8_t GZP6877_Wait(void);                  // GZP6877模块等待可读压力和温度
extern int GZP6877_Read_Pressure(void);             // GZP6877模块读取压力
extern float GZP6877_Read_Temperature(void);       // GZP6877模块读取温度
extern void GZP6877_Read_Data(void);                // 打印气压和温度
/**====================================================#######  END  #######=================================================*/#endif /* APPLICATIONS_GZP6877D_H_ */

3.main.c

#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>#include "gzp6877d.h"int main(void)
{int count = 1;GZP6877_GPIO_Init();while (count){if (GZP6877_Wait()){continue;}GZP6877_Read_Data();rt_thread_mdelay(500);}return RT_EOK;
}

五、测试验证

  通过软件IIC和硬件IIC进行通信,都可以实现温度和气压的读取,实现的效果如下所示:
在这里插入图片描述
在这里插入图片描述


这篇关于【STM32】RTT-Studio中HAL库开发教程六:IIC通信--GZP6877D气压传感器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1109919

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta