外设驱动库开发笔记50:HP203B气压传感器驱动

  在我们的项目中,经常会有需要检测大气压力的时候。这次我们在大气环境监测的过程中用到了HP203B这款气压传感器。所以这一篇中,我们来思考HP203B气压传感器的驱动设计。

1、功能概述

  HP203B是高分辨率(0.1meter)压力传感器,带有I²C接口,包括一个硅压阻压力元件和一个高分辨率24 位△∑ADC。HP203B提供高精度24位压力和温度数字输出,客户可以根据应用需要转换速度和高度,所有内置计算采用了高速4MHz的浮点运算,计算误差小,数据补偿是内部集成,通讯连接非常简单,高度及温度上下限比较的可编程事件及中断输出控制。

1.1、功能

  HP203B是一款超小型集高精度气压计、高度计和温度计于一体的传感器。内部集成了24位ADC,硅传感芯片,以及存放内部参数的OTP。该传感器通过设计公司获得的专利补偿算法在传感器器件片内进行采样,信号处理以及运算,最终计算出实际的直接结果值,所以外部应用MCU只需发出信号采集命令,待完成后,再通过I²C接口直接读取压力,温度及绝对海拔高度三者的实际值。具体结构图如下:

  此外,该传感器内部提供了对温度、压力和海拔高度的上下限阈值及中间阀值,并构成的趋势变化的多种事件响应的条件预定设置。当其中任一事件发生达到了预设条件后,在传感器内部状态寄存器会置起相应的标志,并在已经预先设置的相应的中断脚位上输出高电平。

1.2、命令

  HP203B气压传感器通过命令集来实现上位对它的访问。命令集允许用户控制传感器进行配置及结果读取。具体的命令列表如下:

  用户通过上述列表中的命令可以实现对HP203B气压传感器的配置及操作,也可以读取我们检测的数据。

1.3、接口

  HP203B气压传感器使用I2C接口。I²C设备地址如下所示。设备地址的LSB是由CSB脚的状态决定。

  CSB PIN=0: 对应的地址0XEE (write) and 0XEF (read)。
  CSB PIN=1: 对应的地址0XEC (write) and 0XED (read)。

1.4、报文格式

  HP203B气压传感器根据操作命令的不同,可以将通讯的报文格式分为4类。
  第一类:主机发出一个单字节命令的类型。 主机发出设备地址(ID)并跟随写位 W 位,收到答复 ACK 位后,发出命令字节,传感器收到后,地回 ACK.如下是发出一个 SOFT_RST 命令。

  第二类:主机写入寄存器的类型。 主机发出设备地址(ID)并跟随写位 W 位,收到答复 ACK 位后,发出命令字节及一个字节的数据。这种格式仅适用于当用户想要发出一个 WRITE_REG 命令。

  第三类:主机从设备读取寄存器的类型。 在这第三类型中共有两帧并分别发送。第一帧是发送包含高 2 位二进制数 10 及后面跟着低 6 位的寄存器地址的 READ_REG 命令。第一帧的格式与第一类的相同。在第二帧,该传感器将发送回寄存器中的数据当收到正确的设备地址及读位(R)之后。这种类型仅适用于使用 READ_REG 命令。

  第四类:主机从设备读3个字节或6个字节的ADC数据。

  其中,第四类是我们最常使用的,笔记我们的目的就是获取气压的监测数据。

2、驱动设计与实现

  在前面我们简单的描述了HP203B气压传感器的基本情况,接下来我们将据此来设计HP203B气压传感器的驱动程序。

2.1、对象定义

  我们依然使用基于对象的方式来设计HP203B气压传感器的驱动。所以我们首先考虑HP203B气压传感器对象类型的定义。关于对象,我们知道器包含属性和操作。
  我们先来考虑HP203B气压传感器对象的属性问题。对于I2C设备,都有一个设备地址,这一地址用以表示该设备在总线上的唯一存在,所以我们将设备地址作为属性,来记录该设备的特性。同样的,HP203B气压传感器用以监测气压、温度和海拔,这几个参数标识HP203B气压传感器对象当前的状态,所以我们将器作为对象的属性。
  接下来我们考虑对象的操作。对象的操作有很多,但我们只需要考虑那些需要依赖于具体的软硬件平台才能实现的定义为对象的操作。而HP203B气压传感器作为I2C接口的设备,与平台相关的就是I2C接口的读写,所以我们将通过I2C读写数据的过程定义为对象的操作。
  基于这些分析,我们定义HP203B气压传感器的对象类型如下:

/*定义HP203B对象类型*/
typedef struct Hp203bObject {
    uint8_t deviceAddress;
    uint32_t cTemperature;
    uint32_t cPressure;
    uint32_t cAltitude;
    float fTemperature;
    float fPressure;
    float fAltitude;
    void (*Receive)(struct Hp203bObject *hp,uint8_t *rData,uint16_t rSize);    //接收数据操作指针
    void (*Transmit)(struct Hp203bObject *hp,uint8_t *tData,uint16_t tSize);   //发送数据操作指针
}Hp203bObjectType;

  定义了HP203B气压传感器对象类型,我们可以得到相应的对象变量,但这一对象变量并不可以使用,需要对其属性和操作进行初始化配置才能使用。所以我们还需要设计以个初始化函数对对象变量进行初始化操作。在这里我们根据设定的HP203B气压传感器对象的属性和操作来实现对象的初始化函数如下:

/*HP203B对象初始化*/
void Hp203bInitialization(Hp203bObjectType *hp,
                          uint8_t deviceAddress,
                          Ph203bReceiveType recieve,
                          Ph203bTransmitType transmit)
{
    if((hp==NULL)||(recieve==NULL)||(transmit==NULL))
    {
        return;
    }
    
    hp->Receive=recieve;
    hp->Transmit=transmit;
    
    if((deviceAddress==0xEE)||(deviceAddress==0xEC))
    {
        hp->deviceAddress=deviceAddress;
    }
    else if((deviceAddress==0x77)||(deviceAddress==0x76))
    {
        hp->deviceAddress=(deviceAddress<<1);
    }
    else
    {
        hp->deviceAddress=0;
    }
    
    /*软复位命令*/
    Hp203bSoftReset(hp);
}

2.2、对象操作

  我们实现了HP203B气压传感器对象类型的定义,接下来我们考虑我们需要对HP203B气压传感器实时的操作。根据前面我们对操作命令及操作报文的了解,我们对HP203B气压传感器的操作主要是对寄存器的访问和对数据的访问。

2.2.1、访问寄存器

  对寄存器的访问包括都寄存器的值和写寄存器的值,根据响应的指令和所要操作的寄存器地址,我们可以实现读写寄存器的操作函数如下:

/*读寄存器值*/
uint8_t Hp203bReadRegister(Hp203bObjectType *hp,Hp203bRegisterType reg)
{
    uint8_t cmd=CMD_ANA_CAL;
    uint8_t rData=0;
    
    hp->Transmit(hp,&cmd,1);
    
    hp->Receive(hp,&rData,1);
    
    return rData;
}

/*写寄存器值*/
void Hp203bWriteRegister(Hp203bObjectType *hp,Hp203bRegisterType reg,uint8_t value)
{
    uint8_t cmd[2];
    
    cmd[0]=CMD_WRITE_REG;
    cmd[1]=value;
    hp->Transmit(hp,cmd,2);
}

2.2.2、访问测量值

  我们对HP203B气压传感器的操作最终都是为了获取气压、温度和海拔的测量值。HP203B气压传感器使用不同的操作命令来获取不同的测量值,这里我们以读取气压和温度测量值为例。

/*读取温度和压力值*/
void Hp203bReadTemperaturPressure(Hp203bObjectType *hp)
{
    uint8_t cmd=CMD_READ_PT;
    uint8_t rData[6];
    uint32_t temp=0;
    
    hp->Transmit(hp,&cmd,1);
    
    hp->Receive(hp,rData,6);
    
    hp->cTemperature=(rData[0]<<16)+(rData[1]<<8)+rData[2];
    
    if(rData[0]>0x0F)
    {
        hp->cTemperature=hp->cTemperature|0xFFF00000;
        temp=~(hp->cTemperature-0x01);
        hp->fTemperature=0.0-(float)temp/100.0;
    }
    else
    {
        hp->fTemperature=(float)hp->cTemperature/100.0;
    }
    
    hp->cPressure=(rData[3]<<16)+(rData[4]<<8)+rData[5];
    hp->fPressure=(float)(hp->cPressure)/100.0;
}

3、驱动的使用

  我们已经设计并实现了HP203B气压传感器对象的驱动程序,接下来我们将使用这一驱动程序实现对HP203B气压传感器的操作。

3.1、声明并初始化对象

  在实现对HP203B气压传感器的操作之前,我们先声明一个HP203B气压传感器的对象变量。

Hp203bObjectType hp203b;

  声明的这个对象变量,我们需要先对其进行初始化。初始化函数有4个参数,第一个是所要初始化的对象变量。第二个参数是该对象变量所表示的设备的地址。这些直接输入就可以,主要是后2个参数为发送和接收函数的函数指针,这两个函数我们需要实现。其函数原型如下:

/*接收数据操作指针*/
typedef void (*Ph203bReceiveType)(struct Hp203bObject *hp,uint8_t *rData,uint16_t rSize);    
/*发送数据操作指针*/
typedef  void (*Ph203bTransmitType)(struct Hp203bObject *hp,uint8_t *tData,uint16_t tSize); 

  根据函数原型要求,并结合我们所采用的软硬件平台,我们可以实现数据的发送及接收函数如下:

/*从Hp203b接收数据*/
static void ReceiveFromHp203b(Hp203bObjectType *hp,uint8_t *rData,uint16_t rSize)
{
    HAL_I2C_Master_Receive(&hi2c1,hp->deviceAddress,rData, rSize, 1000);
}

/*向Hp203b传送数据*/
static void TransmitToHp203b(Hp203bObjectType *hp,uint8_t *tData,uint16_t tSize)
{
    HAL_I2C_Master_Transmit(&hi2c1,hp->deviceAddress,tData,tSize,1000);
}

  根据上述的说明及实现,我们可以使用初始化函数对HP203B气压传感器对象变量进行初始化配置。

/*HP203B对象初始化*/
    Hp203bInitialization(&hp203b,
                         0xEC,
                         ReceiveFromHp203b,
                         TransmitToHp203b);
    
    HAL_Delay(100);
    /*OSR设定,通道选择,执行转换*/
Hp203bConvertSetting(&hp203b,Hp203b_OSR_4096,Hp203b_P_T_Channel);

  初始化对象变量的同时,实现了转换方式及转换通道的配置。

3.2、基于对象进行操作

  完成HP203B气压传感器的基本配置后,我们就可以定时获取压力和温度数据了。先调用压力温度获取函数:

Hp203bReadTemperaturPressure(&hp203b);

  正确读取后,通过访问对象变量hp203b的fTemperature和fPressure属性就可以得到我们想要的数据了。

4、应用总结

  这一篇中,我们设计并实现了HP203B气压传感器的驱动程序。我们将这一驱动应用到实际的项目中,系统运行稳定。

欢迎关注:

posted @ 2023-01-08 19:26  Moonan  阅读(324)  评论(0编辑  收藏  举报