STM32应用实例八:与多台MS5803压力传感器I2C通讯
MS5803压力传感器支持SPI和I2C总线通讯,拥有24位AD转换。能够同时获得压力值和温度值,其中压力测量范围为10-1100mbar,温度的测量范围是-40-85摄氏度。各引脚功能及参数如下:
传感器内部结构图如下:
通讯协议的选择通过PS引脚来设置:
PS引脚电位 |
通讯模式 |
使用的引脚 |
高电平 |
I2C |
SDA, SCL, CSB |
低电平 |
SPI |
SDI, SDO, SCLK, CSB |
在SPI模式下,SCLK作为外部输入时钟,SDI作为串行数据输入,支持Mode0和Mode3的时钟极性和相位。传感器的响应数据输出为SDO引脚,片选信号为CSB引脚。界限示意图如下:
在I2C模式下,SCLK为外部串行时钟输入,SDA位串行数据通讯。CSB引脚作为地只选择,可以链接到VDD或者GND,这也意味着MS5803可以在一条I2C总线接两个设备。在CSP接高电平时,地址为0x76(1110110 b),而CSB接低电平时,地址为0x77 (1110111 b)这个地址是高七位,最后以为有读写命令来决定。实现写命令时,最后一位为0,实现读命令时,最后一位为1。
MS5803拥有5个基本命令:复位、读取出厂校准值、数据1转换(压力值数据)、数据2转换(温度值数据)和读取ADC的转换结果。具体分配如下:
因为MS5803的地址位仅有1位是可以设定的,所以一条I2C总线最多只能挂2个MS5803模块。为了让程序具有较好的可移植性,我们在便写程序时不使用对硬件的直接操作,而采用函数指针来操作,所以我们定义了:
/*向MS5803下发指令,指令格式均为1个字节*/
typedef void (*WriteCommandToMS5803Type)(uint8_t deviceAddress,uint8_t command);
/*从MS5803读取多个字节数据的值*/
typedef void (*ReadBytesFromMS5803Type)(uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum);
以上两个函数指针来实现针对硬件的读写操作。接下来我们开始编写代码。
(1)复位操作
复位操作的数据流如下图所示,只需要发送一条命令就可完成:
/*复位MS5803操作*/ void ResetForMS5803(uint8_t deviceAddress,WriteCommandToMS5803Type WriteCommandToMS5803) { uint8_t command=COMMAND_RESET; /*下发复位命令*/ WriteCommandToMS5803(deviceAddress,command); }
(2)读取校准值
校准值是出厂时厂家校准的各种系数,每台设备都有差异,是固定不变的,只需要一次读取就可以了,共有6个系数,均为16为整数。首先发送读系数的命令,然后读取就可以了,每次读取1个,分6次读取。过程数据流如下图所示:
/*从MS5803的PROM中读取校准数据*/ void GetCalibrationData(uint8_t deviceAddress,uint16_t *caliPara,WriteCommandToMS5803Type WriteCommandToMS5803,ReadBytesFromMS5803Type ReadBytesFromMS5803) { /*C1压力灵敏度*/ caliPara[]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C1,WriteCommandToMS5803,ReadBytesFromMS5803); /*C2压力补偿值*/ caliPara[]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C2,WriteCommandToMS5803,ReadBytesFromMS5803); /*C3压力灵敏度温度系数*/ caliPara[]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C3,WriteCommandToMS5803,ReadBytesFromMS5803); /*C4压力补偿温度系数*/ caliPara[]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C4,WriteCommandToMS5803,ReadBytesFromMS5803); /*C5参考温度*/ caliPara[]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C5,WriteCommandToMS5803,ReadBytesFromMS5803); /*C6温度传感器温度系数*/ caliPara[]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C6,WriteCommandToMS5803,ReadBytesFromMS5803); }
(3)读取转换值
读取转换结果值是我们的目的,可以读取温度和压力两个量,不过一次只能读一个。首先发送命令设定采集压力还是温度,并设定精度。然后发送读取的命令,最后读取对应的值。再使用校准系数计算出最终的物理值。
/*获取转换值,包括温度和压力*/ void GetConversionValue(uint8_t deviceAddress,float *pPres,float *pTemp,uint16_t *caliPara,uint16_t *semaphore,WriteCommandToMS5803Type WriteCommandToMS5803,ReadBytesFromMS5803Type ReadBytesFromMS5803) { uint16_t senst1; //C1压力灵敏度 uint16_t offt1; //C2压力补偿值 uint16_t tcs; //C3压力灵敏度温度系数 uint16_t tco; //C4压力补偿温度系数 uint16_t tref; //C5参考温度 uint16_t tempsens; //C6温度传感器温度系数 /*从MS5803的PROM中读取校准数据*/ if(*semaphore>) { GetCalibrationData(deviceAddress,caliPara,WriteCommandToMS5803,ReadBytesFromMS5803); *semaphore=*semaphore-; } senst1=caliPara[]; offt1=caliPara[]; tcs=caliPara[]; tco=caliPara[]; tref=caliPara[]; tempsens=caliPara[]; uint32_t digitalPressureValue; uint32_t digitalTemperatureValue; /*读取压力数据*/ digitalPressureValue=ReadConversionFromMS5803(deviceAddress,COMMAND_CONVERTD1OSR4096,WriteCommandToMS5803,ReadBytesFromMS5803); Delayms(); /*读取温度数据*/ digitalTemperatureValue=ReadConversionFromMS5803(deviceAddress,COMMAND_CONVERTD2OSR4096,WriteCommandToMS5803,ReadBytesFromMS5803); /*对温度进行一阶修正*/ int32_t dT; int32_t temp; dT=digitalTemperatureValue-tref*; temp=(int32_t)(+dT*tempsens/pow(,)); /*对压力进行一阶修正*/ int64_t off; int64_t sens; int32_t pres; off=(int64_t)(offt1*pow(,)+(tco*dT)/pow(,)); sens=(int64_t)(senst1*pow(,)+(tcs*dT)/pow(,)); pres=(int32_t)((digitalPressureValue*sens/pow(,)-off)/pow(,)); /*对温度和压力进行二阶修正*/ int64_t ti=; int64_t offi=; int64_t sensi=; int64_t off2=; int64_t sens2=; if(temp<) { ti=(int64_t)(*dT*dT/pow(,)); offi=(int64_t)(*(temp-)*(temp-)/pow(,)); sensi=(int64_t)(*(temp-)*(temp-)/pow(,)); off2=off-offi; sens2=sens-sensi; temp=temp-(int32_t)ti; pres=(int32_t)((digitalPressureValue*sens2/pow(,)-off2)/pow(,)); } if((-<=temp)&&(temp<=)) { *pTemp=(float)temp/100.0; } if((<=pres)&&(pres<=)) { *pPres=(float)pres/100.0; } }
最终在STM32的I2C接口实现通讯时,实现2个WriteCommandToMS5803Type(uint8_t deviceAddress,uint8_t command);和ReadBytesFromMS5803Type(uint8_t deviceAddress,uint8_t *pData,uint16_t bytesNum);函数并调用就可以了,换做其他的平台也只需要重写这两个函数就能实现通讯了。
STM32应用实例八:与多台MS5803压力传感器I2C通讯的更多相关文章
- STM32应用实例七:与宇电设备实现AI-BUS通讯
宇电的设备使用基于RS-485的自定义协议,协议本身比较简单,只有2条指令: 读:地址代号+52H(82) +要读的参数代号+0+0+校验码 写:地址代号+43H(67)+要写的参数代号+写入数低字节 ...
- 【转载】stm32的GPIO八种工作模式
一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止.高低电平由IC的电源决定. 推挽电路是两个参数 ...
- C语言库函数大全及应用实例八
原文:C语言库函数大全及应用实例八 [编程资料]C语言库函数大全及应用实例八 函数名: kbhit 功 能: 检查 ...
- STM32应用实例十:简析STM32 I2C通讯死锁问题
I2C接口是一种使用非常普遍的MCU与外部设备的接口方式,在STM32中也集成了I2C接口,我们也常常使用它来与外围的传感器等设备通讯. 最近在我们使用STM32F1VET6读取压力和温湿度传感器数据 ...
- STM32应用实例六:与MS5837压力传感器的I2C通讯
MS5837压力传感器是一种可用于电路板上,适用于检测10-1200mbar压力范围的传感器,灵敏度非常高,理论上能够检测到0.01mbar的压力变化,实际使用过程中测试并无明显的变化. MS5837 ...
- 两台电脑使用ROS通讯
一.ROS分布式多机通讯简介 ROS是一种分布式软件框架,节点之间通过松耦合的方式组合,在很多应用场景下,节点可以运行在不同的计算平台上,通过Topic,Service通信. 但是各个节点只能共同拥有 ...
- stm32 IO口八种模式区别
初学STM32,遇到I/O口八种模式的介绍,网上查了一下资料,下面简明写出这几种模式的区别,有不对的地方请大家多多指正! 上拉输入模式:区别在于没有输入信号的时候默认输入高电平(因为有弱上拉).下拉输 ...
- XAML实例教程系列 - XAML传递参数到值转换类实例 八
Kevin Fan分享开发经验,记录开发点滴 XAML实例教程系列 - XAML传递参数到值转换类实例 2012-06-28 05:25 by jv9, 508 阅读, 0 评论, 收藏, 编辑 继上 ...
- eureka多实例,模拟多台机器
本文只有一个eureka server项目,运行在不同的端口,模拟两台eureka服务.开发使用eclipse 4.8 先说pom.xml文件,如果出现问题,首先考虑springboot和其他包版本冲 ...
随机推荐
- 目标检测网络之 Mask R-CNN
Mask R-CNN 论文Mask R-CNN(ICCV 2017, Kaiming He,Georgia Gkioxari,Piotr Dollár,Ross Girshick, arXiv:170 ...
- 斯坦福大学公开课机器学习:Neural network-model representation(神经网络模型及神经单元的理解)
神经网络是在模仿大脑中的神经元或者神经网络时发明的.因此,要解释如何表示模型假设,我们先来看单个神经元在大脑中是什么样的.如下图,我们的大脑中充满了神经元,神经元是大脑中的细胞,其中有两点值得我们注意 ...
- OpenCV 无法启动此程序,因为计算机中丢失opencv_core249.dll。请尝试重新安装改程序已解决此问题
换了64位的系统,配置好之后运行之前的程序,竟然给我抛出这个错误.应该是我的opencv没有安装对吧.系统报错 无法启动此程序,因为计算机中丢失opencv_core249.dll.请尝试重新安装改程 ...
- 九、java容器
目录 一.容器的概念 二.Cpllection接口 三.Iterator接口 四.增强的for循环 五.Set接口 六.List接口和Comparable接口 八.Map接口 九.自动打包/解包 十. ...
- 利用ansible-playbook从测试环境获取tomcat中java项目新版本发布到生产环境
一.环境描述 安装有ansible的服务器:192.168.13.45 测试环境服务器:192.168.13.49 /home/app/api-tomcat/webapps/api.war为测试环境新 ...
- 集合总结(全是代码)----------java基础学习
前言:在刚学习的时候,切记不能粘贴复制,更不能眼高手低,再简单的代码,都要自己独立动手写. 第一步:目录结构 第二步:代码区 Student.java:(一个学生的实体类) package com.m ...
- 1024. Palindromic Number (25)
A number that will be the same when it is written forwards or backwards is known as a Palindromic Nu ...
- SpringBoot使用redis缓存List<Object>
一.概述 最近在做性能优化,之前有一个业务是这样实现的: 1.温度报警后第三方通讯管理机直接把报警信息保存到数据库 2.我们在数据库中添加触发器,(BEFORE INSERT)根据这条报警信息处理业务 ...
- Django 2.0.1 官方文档翻译:编写你的第一个djang补丁(page 15)
编写你的第一个djang补丁(page 15) 介绍 有兴趣为社区做一些贡献?可能你发现了django中的一个你想修复的bug,或者你你想添加一个小小的功能. 回馈django就是解决你遇到的问题的最 ...
- .Net进阶系列(11)-异步多线程(委托BeginInvoke)(被替换)
一. BeginInvoke最后两个参数的含义 倒数第二个参数:指该线程执行完毕后的回调函数:倒数第一个参数:可以向回调函数中传递参数. 下面以一段代码说明: /// <summary> ...