外设驱动库开发笔记16:MS5536C压力变送器驱动

压力检测也是经常会遇到的需求,比如环境压力或者低压气体等都会用到压力检测。这类检测压力都比较低,一般不会超过大气压,有时甚至是负压。这一篇我们要讨论的MS5536C就属于这类器件。接下来我们将设计并实现MS5536C的驱动。

1、功能概述

MS5536C是一个系列的高分辨率工厂校准压力传感器。该设备包括一个压阻式压力传感器和一个ADC,采用三线SPI接口。该设备以16位数据字的形式提供数字压力和温度信息。其结构图如下:

MS5536C包含压阻传感器和传感器接口ICMS5536C的主要功能是将压阻压力传感器的模拟输出电压为一个16位数字的值,以及提供一个16位数字值的温度传感器。MS5536C通过SPI接口与外界进行数字通讯,其引脚定义如下:

由于压力传感器的输出电压很大程度上取决于温度和工艺公差,因此有必要对这些影响进行补偿。每个模块都是在两个温度和两个压力下单独校准的。因此,计算了6个必要的系数来补偿工艺变化和温度变化,并存储在每个模块的64PROM中。4个字的位排序组合为6个有效系数,具体如下:

对于MS5536C表压传感器,在MCU发送信号时,使用时钟上升沿;在MCU接收数据时,采用时钟下降沿。

2、驱动设计与实现

我们已经了解了MS5536C压力传感器的基本情况。接下来我们将在此基础上设计并实现MS5536C压力传感器的驱动程序。

2.1、对象定义

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

2.1.1、对象的抽象

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

先来考虑属性,作为属性肯定是用于标识或记录对象特征的东西。我们来考虑MS5536C压力传感器对象属性。首先每一台MS5536C设备都有6个校准系数,每次测量都需要使用,所以我们将其作为属性保存下来。另一个,测量的温度压力数据指示了MS5536C的工作状态,所以我们也将其作为属性。

接着我们还需要考虑MS5536C压力传感器对象的操作问题。我们要获取数据就要访问MS5536C的寄存器,就需要向其发送数据和从其接收数据,但读写操作通常依赖于具体硬件平台,所以我们将读写行为作为对象的操作。访问MS5536C时,发送数据和接收数据分别采用时钟的上升沿和下降沿,这样我们必须修改SPI端口的模式,这同样与硬件平台相关,所以我们将其定义为对象的操作。此外,控制时序需要处理延时,而实现延时同样依赖于具体的软硬件平台,所以我们将延时也作为对象的操作。

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

//定义MS5536C对象类型
typedef struct MS5536cObject {uint16_t coef1;        //校准系数C1uint16_t coef2;        //校准系数C2uint16_t coef3;        //校准系数C3uint16_t coef4;        //校准系数C4uint16_t coef5;        //校准系数C5uint16_t coef6;        //校准系数C6int32_t pressure;     //压力100倍整数值int32_t temperature;  //温度100倍整数值float fPressure;     //压力浮点数值float fTemperature;  //温度浮点数值void (*ReadWriteMS)(uint8_t *txData,uint8_t *rxData,uint16_t number);void (*Delayms)(volatile uint32_t Delay);void (*SetPhase)(MS5536cPhaseType phase);
}MS5536cObjectType;

2.1.2、对象初始化

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

/* 对MS5536C对象进行初始化 */
void Ms5536cInitialization(MS5536cObjectType *ms,MS5536cReadWriteMS readwrite,MS5536cSetPhase setPhase,MS5536cDelayms delayms)
{if((ms==NULL)||(readwrite==NULL)||(setPhase==NULL)||(delayms==NULL)){return;}ms->ReadWriteMS=readwrite;ms->SetPhase=setPhase;ms->Delayms=delayms;ms->coef1=0;ms->coef2=0;ms->coef3=0;ms->coef4=0;ms->coef5=0;ms->coef6=0;ms->pressure=0;ms->fPressure=0.0;ms->temperature=0;ms->fTemperature=0.0;//复位Ms5336cSoftwareReset(ms);ms->Delayms(10);//获取修正系数GetCoefficientForMs5536c(ms);
}

2.2、对象操作

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

2.2.1、测量数据读取

MS5536C中,压力数据、温度数据以及校准系数的获取器操作是类似的,我们只需要操作响应的寄存器就好了,所以我们一并考虑它们。

MS5536C中,压力数据是一个16位的数据,读取的时序需要在发送命令和接受数据时采用不同的时钟沿。

MS5536C中,温度数据是一个16位的数据,读取温度数据的时序与压力数据一样,也需要在发送命令和接收数据时采用不同的时钟沿。

数据转换需要时间,所以在发送命令后要等待33毫秒,根据上述时序图,我们可以分析并设计读取转换数据的操作如下:

/* 读取测量数据 */
static uint16_t ReadMeasureData(MS5536cObjectType *ms,uint16_t command)
{uint8_t txData[2];uint8_t rxData[2];uint16_t result=0;txData[0]=(uint8_t)(command>>8);txData[1]=(uint8_t)command;ms->ReadWriteMS(txData,rxData,2);ms->Delayms(23);ms->SetPhase(MS5536_SCLK_FALL);ms->Delayms(10);txData[0]=0x00;txData[1]=0x00;ms->ReadWriteMS(txData,rxData,2);result=(rxData[0]<<8)+rxData[1];ms->SetPhase(MS5536_SCLK_RISE);ms->Delayms(10);return result;
}

2.2.2、寄存器读取

MS5536C中,修正系数是有4个字组成,其实是6个系数,前面已经介绍了它的格式,读取这几个数据的时序也需要在发送命令和接受数据时采用不同的时钟沿。字1和字3的时序图如下:

读取字2和字4的时序图如下:

根据上述时序图,我们可以分析并设计读取寄存器的操作如下:

/* 读取寄存器值 */
static uint16_t ReadRegister(MS5536cObjectType *ms,uint16_t command)
{uint8_t txData[2];uint8_t rxData[2];uint16_t result=0;txData[0]=(uint8_t)(command>>8);txData[1]=(uint8_t)command;ms->ReadWriteMS(txData,rxData,2);ms->SetPhase(MS5536_SCLK_FALL);txData[0]=0x00;txData[1]=0x00;ms->ReadWriteMS(txData,rxData,2);result=(rxData[0]<<8)+rxData[1];ms->SetPhase(MS5536_SCLK_RISE);ms->Delayms(1);return result;
}

2.2.3、系统复位

复位信号的序列是特殊的,因为它的独特模式是由模块在任何状态下识别的。因此,如果微控制器和MS5536C之间的同步丢失,它可以用来重新启动。这个序列是21位长。DOUT信号可能在这一序列中发生变化。建议在第一次转换序列之前发送复位序列,以避免在电气干扰情况下永久挂起协议。其时序图如下:

/*对MS5336C进行软件复位*/
void Ms5336cSoftwareReset(MS5536cObjectType *ms)
{//命令为21位:10101010 10101010 00000uint8_t command[3]={170,170,0};uint8_t rxDate[3];ms->ReadWriteMS(command,rxDate,3);
}

3、驱动的使用

我们设计并实现了MS5536C压力传感器的驱动程序,我们还要设计一个简单的应用来验证这个驱动程序设计是否正确。所以接下来我们就基于驱动设计一个应用。

3.1、声明并初始化对象

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

MS5536cObjectType ms5536;

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

MS5536cObjectType *msMS5536对象

MS5536cReadWriteMS readwrite,读写操作

MS5536cSetPhase setPhase,相位设置操作

MS5536cDelayms delayms,延时操作

对于这些参数,对象变量我们已经定义了。所需要考虑的主要是我们需要定义几个函数,并将函数指针作为参数。这几个函数的类型如下:

typedef void (*MS5536cReadWriteMS)(uint8_t *txData,uint8_t *rxData,uint16_t number);typedef void (*MS5536cDelayms)(volatile uint32_t Delay);typedef void (*MS5536cSetPhase)(MS5536cPhaseType phase);

对于这几个函数我们根据样式定义就可以了,具体的操作可能与使用的硬件平台有关系。具体函数定义如下:

/* 通过SPI端口发送数据 */
static void ReadWriteBySPI(uint8_t *txData,uint8_t *rxData,uint16_t number)
{HAL_SPI_TransmitReceive(&ms5536hspi,txData,rxData,number,1000);
}/* SPI1 初始化配置 */
static void MS5536_SPI_Configuration(MS5536cPhaseType phase)
{/* SPI1 端口参数配置*/ms5536hspi.Instance = SPI1;ms5536hspi.Init.Mode = SPI_MODE_MASTER;ms5536hspi.Init.Direction = SPI_DIRECTION_2LINES;ms5536hspi.Init.DataSize = SPI_DATASIZE_8BIT;ms5536hspi.Init.CLKPolarity = SPI_POLARITY_LOW;if(phase==MS5536_SCLK_RISE){ms5536hspi.Init.CLKPhase = SPI_PHASE_1EDGE;}else{ms5536hspi.Init.CLKPhase = SPI_PHASE_2EDGE;}ms5536hspi.Init.NSS = SPI_NSS_SOFT;ms5536hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;ms5536hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;ms5536hspi.Init.TIMode = SPI_TIMODE_DISABLE;ms5536hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;ms5536hspi.Init.CRCPolynomial = 7;if (HAL_SPI_Init(&ms5536hspi) != HAL_OK){}
}

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

Ms5536cInitialization(&ms5536,ReadWriteBySPI,MS5536_SPI_Configuration,HAL_Delay);

3.2、基于对象进行操作

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

/*压力数据处理*/
void PresDataProcess(void)
{float pressure=0.0;float temperature=0.0;GetMeasureForMs5536c(&ms5536);pressure=ms5536.fPressure;temperature=ms5536.fTemperature;
}

4、应用总结

我们设计了MS5536C压力传感器的驱动程序,并且设计了一个简单的应用来验证它。事实上,在此之前我们已经在项目中使用过MS5536C压力传感器,并且正确的得到了我们想要的数据。

使用时需要注意,MS5536C压力传感器采用的是SPI接口,但没有片选信号。在发送信号时以3为高电平起始。在MCU发送信号时,使用时钟上升沿;在MCU接收数据时,采用时钟下降沿。关于上升沿和下降沿转换这一点需特别注意,否则读取的数据不正确。

源码已发布:https://github.com/foxclever/ExPeriphDriver

欢迎关注:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499346.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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

很多时候我们需要检测被控对象的绝对压力&#xff0c;而且在我们的多款产品中也有这样的需求。当然检测绝对压力的传感器有很多&#xff0c;我们经常使用MS5803来实现压力检测。本篇中我们将设计并实现MS5803系列压力传感器的驱动。 1、功能概述 MS5803系列产品包含压阻传感器…

通讯接口应用笔记1:RS485通讯上下拉电阻的选择

RS485是一种常见的通讯接口方式&#xff0c;在我们的实际产品中也是多次使用。但我们平常并不会去过多考虑某一实现的细节问题&#xff0c;不过最近我们遇到了一个因如上下拉电阻的选择问题而造成的通讯故障&#xff0c;所以在这一片中我们来讨论一下RS485总线上下拉电阻的选择…

外设驱动库开发笔记18:MS5837压力变送器驱动

绝对压力的检测是常见的需求。在我们的系统中也常常会遇到。而MS5837压力传感器也是我们进场会采用的方案。在这篇里我们将讨论并实现MS5837压力传感器的驱动。 1、功能概述 MS5837压力传感器是一种可用于电路板上&#xff0c;适用于检测10-1200mbar压力范围的传感器&#xf…

外设驱动库开发笔记19:BMP280压力温度传感器驱动

压力和温度监测在嵌入式系统开发中是非常常见的需求&#xff0c;特别是对环境大气压力和温度的检测需求就更常见了。我们一般都会选择一些封装较小操作比较方便的压力传感器。BMP280就是满足这一要求的器件。在这一篇中我们将设计并实现BMP280的驱动。 1、功能概述 BMP280是一…

一个简单的空气质量数据监测站项目

大气质量数据监测站用于测试空气质量监测及数据采集&#xff0c;实现野外或者室内空气质量的检测。并通过网络将数据上传到OneNet​显示。​ 1、项目概述 本项目是一个定制项目&#xff0c;要求采集大气的压力、温度、湿度、PM25、位置等数据并上传到指定的后台服务器。但有时…

一个基于STM32实现的多组分气体分析仪项目

本篇将简要的总结一下一个基于STM32F412ZG实现的多组分气体分析仪的项目。简要描述该项目的软硬件设计及其验证。 一、项目概述 多组分气体分析仪是我公司近期研发的三个主要产品之一。采用模块化设计&#xff0c;可增减配置&#xff0c;可分析混合气体中的氧气、氢气、甲烷、…

外设驱动库开发笔记20:BME280压力湿度温度传感器驱动

嵌入式产品开发中&#xff0c;我们常常会有检测环境温度、压力、湿度的需求。如果有一个集成有这3个传感器的元件&#xff0c;无疑将是很方便的。博世的BME280就能实现这一要求。在这一篇中我们将讨论BME280的驱动设计与实现。 1、功能概述 BME280是一款专为移动应用而开发的…

外设驱动库开发笔记21:BME680环境传感器驱动

环境传感器是一类我们很常用的传感器。它可以方便我们获取压力、温度、湿度以及空气质量等数据。在这一篇中&#xff0c;我们将分析BME680环境传感器的功能&#xff0c;并设计和实现BME680环境传感器的驱动。 1、功能概述 BME680是一款专为移动应用和可穿戴设备开发的集成环境…

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

移动设备的广泛应用增加对移动过程中各种参数的检测需求。ADXL345三轴数字加速度计可以用来检测加速度、进而测量倾斜角度等。在这一篇中&#xff0c;我们将讨论ADXL345三轴数字加速度计驱动程序的设计与实现。 1、功能概述 ADXL345是一款小而薄的超低功耗3轴加速度计&#x…

外设驱动库开发笔记23:AT24Cxx外部存储器驱动

在我们的应用开发过程中&#xff0c;经常会使用到外部的EEPROM外部存储器来保存一些参数和配置数据等。而比较常用的就是AT24Cxx系列产品&#xff0c;这一节我们来开发用于操作AT24Cxx系列产品的驱动。 1、功能概述 AT24Cxx系列EEPROM包括从1Kbit到2Mbit的各种容量。AT24Cxx系…

外设驱动库开发笔记24:FM24xxx系列FRAM存储器驱动

虽然说使用EEPROM保存参数很有效&#xff0c;但操作及使用次数均有一下限制。当我们的一些参数需要不定时修改或存储时&#xff0c;使用FRAM就更为方便一点。这一节我们就来设计并实现FM24xxx系列FRAM的驱动。 1、功能概述 我们首先说一下铁电随机存取存储器&#xff0c;F-RA…

外设驱动库开发笔记25:FM25xxx FRAM存储器驱动

在我们的项目中&#xff0c;时常会有参数或数据需要保存。铁电存储器的优良性能和操作方便常常被我们选用。FM25xxx FRAM存储器就是我们经常使用到的一系列铁电存储器&#xff0c;这一篇我们将讨论FM25xxx FRAM存储器的驱动设计、实现及使用。 1、功能概述 FM25xxx FRAM存储器…

步进电机驱动技术1:基于TMC2660的步进电机驱动

步进电机的应用非常广泛&#xff0c;在各种设备中经常会遇到&#xff0c;而步进电机的驱动则是使用步进电机必不可少的部分&#xff0c;可以有多种方式来实现步进电机的驱动&#xff0c;在这里我们来考虑一下基于TMC2660驱动芯片的步进电机驱动。 1、功能概述 TMC2660是德国T…

外设驱动库开发笔记26:nRF24L01无线通讯驱动

现在无线在我们的生活中无处不在。而我们开发的物联网产品也大量使用无线通讯。在这一篇文章中&#xff0c;我们将讨论nRF24L01无线通讯模块驱动程序的开发与实现。 1、功能概述 nRF24L01是一款工作在2.4~2.5GHz世界通用ISM 频段的单片无线收发器芯片无线收发器包括&#xff…

外设驱动库开发笔记27:ESP8266无线通讯驱动

我们的物联网产品所使用的平台都支持无线通讯&#xff0c;而且无线通讯本身更的成本较低&#xff0c;受到大家的欢迎。在本篇文章中&#xff0c;我们将详细讨论并实现ESP8266无线通讯模块的驱动。 1、功能概述 ESP8266是由乐鑫公司出品的一款物联网芯片&#xff0c;因为价格较…

外设驱动库开发笔记28:W5500以太网控制器

以太网通讯是一种被广泛使用的数据通讯方式。在嵌入式应用中也经常使用&#xff0c;但协议栈的实现并不是一件容易的事。不过有些以太网控制器就带有协议栈&#xff0c;如W5500。在本篇中我们将讨论如何设计并实现W5500以太网控制器的驱动。 1、功能概述 W5500是WIZnet开发的…

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

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

外设驱动库开发笔记30:宇电AI-BUS通讯驱动

嵌入式系统通常都会与外部设备进行通讯&#xff0c;这就涉及到通讯协议的问题。这些通讯协议有的是标准协议有的厂家自定义的协议&#xff0c;如宇电的AI-BUS。在本篇中&#xff0c;我们将讨论AI-BUS的驱动&#xff0c;以便于与宇电设备的通讯。 1、功能概述 宇电的设备使用基…

步进电机驱动技术3:基于ULN2003的步进电机驱动

在我们的项目中&#xff0c;经常使用到低电压小功率的步进电机&#xff0c;此类步进电机若采用驱动器控制不断成本高也过于复杂&#xff0c;我们可以直接使用场效应管或者达林顿管来实现对其的驱动。在本篇中&#xff0c;我们就来讨论一下基于ULN2003A达林顿管实现对步进电机的…

通讯接口应用笔记2:MAX3160实现多协议通讯

在一些应用需求中&#xff0c;我们需要对外部提供串行通讯端口&#xff0c;但这些端口所通讯的目标设备各有不同&#xff0c;接口协议也有RS232以及RS485和RS422多种。面对这种情况&#xff0c;我们当然可以同时设计多个串口以适应不同需要&#xff0c;但无疑对硬件资源是一种浪…