很多时候我们需要检测被控对象的绝对压力,而且在我们的多款产品中也有这样的需求。当然检测绝对压力的传感器有很多,我们经常使用MS5803来实现压力检测。本篇中我们将设计并实现MS5803系列压力传感器的驱动。

1、功能概述

MS5803系列产品包含压阻传感器和传感器接口IC。MS5803系列压力传感器的主要功能是将未补偿的压阻压力传感器的模拟输出电压24位数字值,以及提供一个24位数字值的温度传感器。

1.1、硬件描述

MS5803系列压力传感器是新一代高分辨率高度计传感器,它是为高度计和高度分辨率为20厘米的变压计优化。能够同时获得压力值和温度值,其中压力测量范围为10-1100mbar,温度的测量范围是-40-85摄氏度。MS5803系列压力传感器各引脚功能如下:

MS5803系列压力传感器具有SPI和I2C总线接口。MS5803系列压力传感器模块包括一个高线性压力传感器和一个超低功率24位ΔΣADC与内部工厂校准系数。它提供一个精确的数字24位压力和温度值和不同的操作模式。传感器内部结构图如下:

我们使用MS5803系列压力传感器时,需要做的就是选择不同的通讯接口与其实现数字通讯的过程。

1.2、通讯接口

MS5803系列压力传感器支持SPI和I2C总线通讯,通过协议选择引脚PS来决定采用什么接口。将协议选择引脚PS拉低,选择SPI协议,将PS拉高,激活I2C总线协议。在不同协议下相关引脚的定义如下:

在不同协议下各引脚所支持的参数是有些许差异的。在SPI接口模式下时钟引脚最大可达20MHz;在I2C接口模式下时钟引脚最大可达200kHz。具体的参数如下图:

在SPI模式下,SCLK作为外部输入时钟,SDI作为串行数据输入,支持Mode0和Mode3的时钟极性和相位。传感器的响应数据输出为SDO引脚,片选信号为CSB引脚。SPI模式下接线示意图如下:

在I2C模式下,SCLK为外部串行时钟输入,SDA为串行数据通讯。CSB引脚作为地址选择,可以链接到VDD或者GND,这也意味着MS5803可以在一条I2C总线接两个设备。在CSP接高电平时,地址为0x76(1110110 b),而CSB接低电平时,地址为0x77 (1110111 b)这个地址是高七位,最后以为有读写命令来决定。实现写命令时,最后一位为0,实现读命令时,最后一位为1。I2C模式下接线图如下:

1.3、数据访问

无论是在SPI模式还是在I2C模式,MS5803系列压力传感器都是通过5类命令实现的。这些命令包括:复位、读取出厂校准值、数据1转换(压力值数据)、数据2转换(温度值数据)和读取ADC的转换结果。具体命令定义如下:

从上图,我们知道每个命令的大小为1字节(8位)。需要说明的是,ADC读取指令后,设备将返回24位结果,PROM读取则是16位结果。PROM的地址使用Ad2、Ad1和Ad0位嵌入到PROM读命令中。关于这128bit PROM的地址分配如下图所示:

MS5803系列压力传感器每个模块都是在两个温度和两个压力下单独校准的。这6个必要的系数来补偿工艺变化和温度变化,就存储在每个模块的128bit PROM中。这些6个系数必须由软件读取,并在程序中使用,将D1和D2转换成补偿的压力和温度值。

2、驱动设计与实现

我们已经了解了MS5803压力传感器基本操作。在此基础上,我们将设计并实现MS5803压力传感器的驱动程序。

2.1、对象定义

在使用一个对象之前我们需要获得一个对象。同样的我们想要MS5803压力传感器就需要先定义MS5803压力传感器的对象。

2.1.1、对象的抽象

我们要得到MS5803压力传感器对象,需要先分析其基本特性。一般来说,一个对象至少包含两方面的特性:属性与操作。接下来我们就来从这两个方面思考一下MS5803压力传感器的对象。

先来考虑属性,作为属性肯定是用于标识或记录对象特征的东西。我们来考虑MS5803压力传感器对象属性。首先MS5803有一系列的产品,不同产品线的补偿计算方式有很大差异,所以我们将产品类型作为属性以区别不同的产品。MS5803拥有SPI和I2C两种通讯方式可供选择,为了确定具体设备所采用的接口,我们将其作为对象的属性以记录其使用的接口方式。在采用I2C接口模式时,每台设备都有一个设备地址,这个地址用于区分同一总线上不同的设备,所以我们将地址作为对象的属性。而对于MS5803每台都有6个校准参数,这些参数在测量是需要用到,所以我们需要保存这些参数,所以我们将其作为属性。

接着我们还需要考虑MS5803压力传感器对象的操作问题。无论是使用SPI接口还是使用I2C接口我们都需要向MS5803写命令和从MS5803读数据,而读写行为都与所处的硬件平台相关,所以我们将读和写数据作为对象的操作。为控制时序,我们需要延时操作,但延时操作也与具体的软硬件平台相关,所以我们将其作为对象的操作。在使用SPI接口方式时,若使用软件控制片选信号,则会依赖于硬件,我们将针对片选信号的操作作为对象的操作。

根据上述我们对MS5803压力传感器的分析,我们可以定义MS5803压力传感器的对象类型如下:

typedef struct MS5803Object {uint8_t devAddress;                 //设备地址MS5803PortType port;            //通讯端口协议MS5803ModelType model;    //设备的类型uint16_t caliData[6];        //校准数据float temperature;float pressure;void (*Write)(struct MS5803Object *ms,uint8_t command);//向MS5803写信息void (*Read)(struct MS5803Object *ms,uint8_t *rData,uint16_t rSize);//从MS5803读数据void (*ChipSelcet)(MS5803CSType en);     //片选信号,用于SPI接口void (*Delayms)(volatile uint32_t nTime);     //毫秒秒延时函数
}MS5803ObjectType;

2.1.2、对象初始化

我们知道,一个对象仅作声明是不能使用的,我们需要先对其进行初始化,所以这里我们来考虑MS5803压力传感器对象的初始化函数。一般来说,初始化函数需要处理几个方面的问题。一是检查输入参数是否合理;二是为对象的属性赋初值;三是对对象作必要的初始化配置。据此我们设计MS5803压力传感器对象的初始化函数如下:

/* MS5803对象初始化 */
void MS5803Initialization(MS5803ObjectType *ms,             //MS5803对象MS5803ModelType model,    //类型MS5803PortType port,            //通讯端口uint8_t address,                        //I2C设备地址MS5803Write write,                //写数据函数MS5803Read read,                         //读数据函数MS5803ChipSelcet cs,            //SPI片选信号MS5803Delayms delayms              //毫秒延时)
{if((ms==NULL)||(write==NULL)||(read==NULL)||(delayms==NULL)){return;}ms->Write=write;ms->Read=read;ms->Delayms=delayms;ms->model=model;ms->port=port;if(port==I2C){if((address==0x76)||(address==0x77)){ms->devAddress=(address<<1);}else if((address==0xEC)||(address==0xEE)){ms->devAddress=address;}else{ms->devAddress=0x00;}ms->ChipSelcet=cs;}else{ms->devAddress=0xFF;if(cs==NULL){ms->ChipSelcet=MS5803ChipSelect;}else{ms->ChipSelcet=cs;}}ms->pressure=0.0;ms->temperature=0.0;ResetForMS5803(ms);GetMS5803CalibrationData(ms);
}

2.2、对象操作

我们已经完成了MS5803压力传感器对象类型的定义和对象初始化函数的设计。但我们的主要目标是获取对象的信息,接下来我们还要实现面向MS5803压力传感器的各类操作。

对MS5803压力传感器的其实就是基于前面我们所说的命令来实现的。根据这些命令的作用,我们可以大致分为三个方面:设备复位、ADC转换配置及数据获取、校准系数的获取。下面我么五年就从这三个方面来看一看MS5803压力传感器的操作。

2.2.1、复位操作

复位操作可以在电源供电后的任意时刻发送,但一般要求在开机后首先发送复位程序。这样可以确保校准PROM加载到内部寄存器。当然复位操作也可以用来重置设备ROM以便从我们未知的情况中恢复。

在使用SPI通讯接口时,无论是模式0还是模式3其操作是一样的,SPI方式下的时序图如下:

在I2C通讯接口时,有时候通讯可能会出现SDA被未定义的状态阻塞的时候,可以通过复位操作来恢复通讯。I2C方式下的时序图如下:

/*复位MS5803操作*/
void ResetForMS5803(MS5803ObjectType *ms)
{uint8_t command=COMMAND_RESET;/*下发复位命令*/ms->Write(ms,command);ms->Delayms(3);
}

2.2.2、读取校准值

校准值是出厂时厂家校准的各种系数,每台设备都有差异,但每台设备是固定不变的,只需要一次读取就可以了,共有6个系数,均为16为整数。

用户复位后,执行一次PROM的read命令,读取校准PROM的内容,计算校准系数。关于PROM我们前面已经描述过了,总共有8个地址,地址0包含工厂数据和设置,地址1-6校准系数,地址7包含串行代码和CRC。

在SPI接口通讯模式下,我们发送都对应地址的命令,等待接收数据即可。命令为8位,返回数据为16位,时序图如下:

在I2C接口通讯模式下,PROM读命令由两部分组成。第一个命令将系统设置为PROM读模式。第二部分从系统中获取数据。首先发送读系数的命令,然后读取就可以了,每次读取1个,分6次读取。I2C模式下的时序图如下所示:

/*读取MS5803内存寄存器的数据*/
static uint16_t ReadPromFromMS5803(MS5803ObjectType *ms,uint8_t command)
{/*下发读取指定内存单元的命令*/ms->Write(ms,command);/*接收读取的指定内存单元的值*/uint8_t promValue[2];ms->Read(ms,promValue,2);uint16_t result=(uint16_t)promValue[0];result=(result<<8)+(uint16_t)promValue[1];return result;
}

2.2.3、读取转换值

读取转换结果值是我们的目的,可以读取温度和压力两个量,不过一次只能读一个。首先发送命令设定采集压力还是温度,并设定精度。然后发送读取的命令,最后读取对应的值。再使用校准系数计算出最终的物理值。

对于配置转换及读取转换的结果,在SPI接口模式下,按两步实现:先设置转换精度,等待转换结束再读取数据。具体的时序图如下:

对于配置转换及读取转换的结果,在I2C接口模式下,按三步实现:先设置转换精度,等待转换结束发送读ADC命令,最后读取数据。具体的时序图如下:

/*读取MS5803ADC的转换值*/
static uint32_t ReadConversionFromMS5803(MS5803ObjectType *ms,uint8_t command)
{/*下发转化对象及精度配置命令*/ms->Write(ms,command);ms->Delayms(10);/*下发读取ADC的命令*/ms->Write(ms,COMMAND_ADC_READ);if(ms->port==I2C){ ms->Delayms(10);}/*接收读取的ADC转换结果*/uint8_t adcValue[3];ms->Read(ms,adcValue,3);uint32_t result=(uint32_t)adcValue[0];result=(result<<8)+(uint32_t)adcValue[1];result=(result<<8)+(uint32_t)adcValue[2];return result;
}

3、驱动的使用

我们已经设计并实现了MS5803压力传感器的驱动程序,这个驱动程序是否符合要求还需要验证。这一节我们就来设计一个简单的应用验证这一驱动程序。

3.1、声明并初始化对象

使用基于对象的操作我们需要先得到这个对象,所以我们先要使用前面定义的MS5803压力传感器对象类型声明一个MS5803压力传感器对象变量,具体操作格式如下:

MS5803ObjectType ms5803;

声明了这个对象变量并不能立即使用,我们还需要使用驱动中定义的初始化函数对这个变量进行初始化。这个初始化函数所需要的输入参数如下:

MS5803ObjectType *ms,MS5803对象

MS5803ModelType model,类型

MS5803PortType port,通讯端口

uint8_t address,I2C设备地址

MS5803Write write,写数据函数

MS5803Read read,读数据函数

MS5803ChipSelcet cs,SPI片选信号

MS5803Delayms delayms,毫秒延时

对于这些参数,对象变量我们已经定义了。设备类型和通讯端口都是枚举,我们只需要根据实际的配置情况选择就可以了。设备地址则在采用I2C通讯时,根据实际输入。我们主要需要关注的是定义几个函数,并将函数指针作为参数。这几个函数的类型如下:

/*向MS5803下发指令,指令格式均为1个字节*/
typedef void (*MS5803Write)(MS5803ObjectType *ms,uint8_t command);/*从MS5803读取多个字节数据的值*/
typedef void (*MS5803Read)(MS5803ObjectType *ms,uint8_t *rData,uint16_t rSize);/*片选信号,用于SPI接口*/
typedef void (*MS5803ChipSelcet)(MS5803CSType en);    /*毫秒秒延时函数*/
typedef void (*MS5803Delayms)(volatile uint32_t nTime);  

对于这几个函数我们根据样式定义就可以了,具体的操作可能与使用的硬件平台有关系。若采用的SPI接口则需注意片选操作,片选操作函数用于多设备需要软件操作时,如采用硬件片选可以传入NULL即可。同样如果采用的是I2C接口,则片选可以传入NULL即可。具体函数定义如下:

/*通过I2C1接口下发命令*/
static void SendCommandToMS5803(MS5803ObjectType *ms,uint8_t command)
{HAL_I2C_Master_Transmit(&ms5803hi2c,ms->devAddress,&command,1,1000);
}/*通过I2C1接口读取数据*/
static void GetDatasFromMS5803(MS5803ObjectType *ms,uint8_t *rData,uint16_t rSize)
{HAL_I2C_Master_Receive(&ms5803hi2c,ms->devAddress,rData,rSize,1000);
}

对于延时函数我们可以采用各种方法实现。我们采用的STM32平台和HAL库则可以直接使用HAL_Delay()函数。于是我们可以调用初始化函数如下:

MS5803Initialization(&ms5803,MS580302BA,I2C,0xEC,SendCommandToMS5803,GetDatasFromMS5803,NULL,HAL_Delay);

这里我们使用的型号是MS580302BA,采用I2C接口,地址为0xEC。因为使用的是I2C接口所以片选输入NULL。

3.2、基于对象进行操作

我们定义了对象变量并使用初始化函数给其作了初始化。接着我们就来考虑操作这一对象获取我们想要的数据。我们在驱动中已经将获取数据并转换为转换值的比例值,接下来我们使用这一驱动开发我们的应用实例。

/*获取压力变送器数据*/
void GetPressureSenserData(void)
{float pressure=0.0;float temperature=0.0;GetMS5803ConversionValue(&ms5803,MS5803_OSR4096,MS5803_OSR4096);pressure=ms5803.pressure;temperature=ms5803.temperature;
}

4、应用总结

在本篇中,我们实现了MS5803压力传感器的驱动程序,并基于驱动程序开发了简单的验证应用。我们也多次在项目中使用MS5803压力传感器,使用的就是这一套驱动程序,应用的效果非常不错。

在使用I2C接口时,引脚CSB应连接到VDD或GND。因为MS5803的地址位仅有1位是可以通过CSB设定的,所以一条I2C总线最多只能挂2个MS5803模块。当CSB接VDD时地址最低位为1;当CSB接GND时地址最低位为0。

在使用驱动时需注意,采用SPI接口的器件需要考虑片选操作的问题。如果片选信号是通过硬件电路来实现的,我们在初始化时给其传递NULL值。如果是软件操作片选则传递我们编写的片选操作函数。

源码下载:https://github.com/foxclever/ExPeriphDriver

欢迎关注:

外设驱动库开发笔记17:MS5803压力变送器驱动相关推荐

  1. 外设驱动库开发笔记0:EPD总体设计

    在产品开发过程中,不可避免需要使用很多外部的元件及传感器,这些元器件也许是板载的,也许是板外的,但不管怎样,为其开发驱动程序都是必须的.每次都需要为这些元器件编写驱动程序.但每次重复编写调试很麻烦,于 ...

  2. 外设驱动库开发笔记22:ADXL345三轴数字加速度计驱动

    移动设备的广泛应用增加对移动过程中各种参数的检测需求.ADXL345三轴数字加速度计可以用来检测加速度.进而测量倾斜角度等.在这一篇中,我们将讨论ADXL345三轴数字加速度计驱动程序的设计与实现. ...

  3. 外设驱动库开发笔记13:MLX90614红外温度传感器驱动

    红外温度传感器一般用于非接触式的温度检测.在我们的系统中经常会有这样的需求.所以我们将其设计为通用的驱动库以备复用.这一篇我们将讲述MLX90614红外温度传感器驱动的设计与实现. 1.功能概述 ML ...

  4. 外设驱动库开发笔记9:SHT1x系列温湿度传感器驱动

    在我们的产品中,经常需要检测温湿度数据.有很多检测温湿度的方法和模块,其中SHT1x系列温湿度传感器就是一种成本较低使用方便的温湿度检测模块.下面我们就来说一说如何实现SHT1x系列温湿度传感器的驱动 ...

  5. 外设驱动库开发笔记33:LCD1602液晶显示屏驱动

      LCD1602是一种工业字符型液晶,能够同时显示16x02即32个字符.LCD1602液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,即可以显示出图形.在这一章我们就来讨论LCD ...

  6. python实现sht驱动_【技术】外设驱动库开发笔记9:SHT1x系列温湿度传感器驱动

    在我们的产品中,经常需要检测温湿度数据.有很多检测温湿度的方法和模块,其中SHT1x系列温湿度传感器就是一种成本较低使用方便的温湿度检测模块.下面我们就来说一说如何实现SHT1x系列温湿度传感器的驱动 ...

  7. 外设驱动库开发笔记54:外设库驱动设计改进的思考

      不知不觉中我们已经发布了五十多篇外设驱动的文章.前段时间有一位网友提出了一些非常中肯的建议,这也让我们开始考虑怎么优化驱动程序设计的问题.在这一篇中我们将来讨论这一问题. 1.问题分析   首先我 ...

  8. 外设驱动库开发笔记29:DS17887实时时钟驱动

    一些时候,在我们的嵌入式产品中需要记录时间,所以我们就需要获取时钟,当然实现的方式多种多样,有的MCU本身就有这一功能,不过精度较低.当我们的应用要求较高时就需要使用专门的实时时钟芯片,如DS1788 ...

  9. 外设驱动库开发笔记35:迪文触摸屏驱动

      有些时候嵌入式系统也需要显示更为复杂的图形,需要更丰富的数据展示.为此,我们需要更大,色彩更丰富,带触屏的显示屏,当然性价比更高就最好了.在我们的项目中遇到此类需求,我们有时会选择DWIN触摸屏. ...

最新文章

  1. 2019天猫双11成交额达2684亿,盘点今年双11有哪些亮点!
  2. Ubuntu 16.04 LTS GNOME版本下载
  3. opencv基础知识-videowriter
  4. 面试:如何实现 MySQL 删除重复记录并且只保留一条
  5. [AGC016B]Colorful Hats
  6. 树莓派内核开发准备(内核源码获取、启动过程、源码目录树)
  7. Python开课复习10
  8. 谈一下对c语言程序设计,谈《C语言程序设计》课程教学.doc
  9. mysql中的lgwr_MySQL Replication和Oracle logical standby的原理对比
  10. jquery的autocomplete在firefox下不支持中文输入法的bug
  11. 搞了很久终于突破了一点瓶颈,fighting!!!!!!!!!!!!!!!!
  12. R 修改安装包默认存放位置的方法
  13. vivado仿真脚本生成
  14. 小猫钓鱼纸牌游戏java_java实现纸牌游戏-小猫钓鱼算法
  15. 部署Unbound实现DNS服务
  16. 用于高速网络的实时且可靠的基于异常的入侵检测
  17. AE动画怎么导出?4种常见导出方式汇总
  18. 如何在PowerPoint中将自定义模板设置为默认模板
  19. shell之大小写转换
  20. Android笔记:将布局转换成图片

热门文章

  1. python妙用桌面计算器
  2. mysql数据库工程师 课程_数据库开发工程师需要学习哪些课程?
  3. 阿里云域名购买与域名解析使用教程---(小白教程)
  4. SOLIDWORKS工程图导出DWG图纸时字体处理方法
  5. HTC Android 系列手机 工程测试命令
  6. 成功的关键是看清大趋势,现在大趋势、大潮流是什么
  7. 用于3D成像显微镜的双螺旋PSF
  8. java parcelable_Android中Parcelable的作用实例解析
  9. 【PHP MySQL】数据库专题 第二课 创建数据库 表
  10. WinCE下GPRS自动拨号软件(GPRS AutoDial)