找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4017|回复: 0
打印 上一主题 下一主题
收起左侧

STM32与多台MS5803压力传感器I2C通讯

[复制链接]
跳转到指定楼层
楼主
ID:272571 发表于 2018-1-6 22:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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)复位操作
复位操作的数据流如下图所示,只需要发送一条命令就可完成:
[url=][/url]
/*复位MS5803操作*/
void ResetForMS5803(uint8_t deviceAddress,WriteCommandToMS5803Type WriteCommandToMS5803)
{
  uint8_t command=COMMAND_RESET;
  /*下发复位命令*/
  WriteCommandToMS5803(deviceAddress,command);
}
[url=][/url]
2)读取校准值
校准值是出厂时厂家校准的各种系数,每台设备都有差异,是固定不变的,只需要一次读取就可以了,共有6个系数,均为16为整数。首先发送读系数的命令,然后读取就可以了,每次读取1个,分6次读取。过程数据流如下图所示:
[url=][/url]
/*从MS5803的PROM中读取校准数据*/
void GetCalibrationData(uint8_t deviceAddress,uint16_t *caliPara,WriteCommandToMS5803Type WriteCommandToMS5803,ReadBytesFromMS5803Type ReadBytesFromMS5803)
{
  /*C1压力灵敏度*/
  caliPara[0]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C1,WriteCommandToMS5803,ReadBytesFromMS5803);
  /*C2压力补偿值*/
  caliPara[1]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C2,WriteCommandToMS5803,ReadBytesFromMS5803);
  /*C3压力灵敏度温度系数*/
  caliPara[2]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C3,WriteCommandToMS5803,ReadBytesFromMS5803);
  /*C4压力补偿温度系数*/
  caliPara[3]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C4,WriteCommandToMS5803,ReadBytesFromMS5803);
  /*C5参考温度*/
  caliPara[4]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C5,WriteCommandToMS5803,ReadBytesFromMS5803);
  /*C6温度传感器温度系数*/
  caliPara[5]=ReadPromFromMS5803(deviceAddress,COMMAND_PROM_READ_C6,WriteCommandToMS5803,ReadBytesFromMS5803);
}
[url=][/url]
3)读取转换值
读取转换结果值是我们的目的,可以读取温度和压力两个量,不过一次只能读一个。首先发送命令设定采集压力还是温度,并设定精度。然后发送读取的命令,最后读取对应的值。再使用校准系数计算出最终的物理值。
  1. /*获取转换值,包括温度和压力*/

  2. void GetConversionValue(uint8_t deviceAddress,float *pPres,float *pTemp,uint16_t *caliPara,uint16_t *semaphore,WriteCommandToMS5803Type WriteCommandToMS5803,ReadBytesFromMS5803Type ReadBytesFromMS5803)

  3. {

  4.   uint16_t senst1;        //C1压力灵敏度

  5.   uint16_t offt1;         //C2压力补偿值

  6.   uint16_t tcs;           //C3压力灵敏度温度系数

  7.   uint16_t tco;           //C4压力补偿温度系数

  8.   uint16_t tref;          //C5参考温度

  9.   uint16_t tempsens;      //C6温度传感器温度系数



  10.   /*从MS5803的PROM中读取校准数据*/

  11.   if(*semaphore>0)

  12.   {

  13.     GetCalibrationData(deviceAddress,caliPara,WriteCommandToMS5803,ReadBytesFromMS5803);

  14.     *semaphore=*semaphore-1;

  15.   }

  16.   senst1=caliPara[0];

  17.   offt1=caliPara[1];

  18.   tcs=caliPara[2];

  19.   tco=caliPara[3];

  20.   tref=caliPara[4];

  21.   tempsens=caliPara[5];

  22.   uint32_t digitalPressureValue;

  23.   uint32_t digitalTemperatureValue;


  24.   /*读取压力数据*/

  25. digitalPressureValue=ReadConversionFromMS5803(deviceAddress,COMMAND_CONVERTD1OSR4096,WriteCommandToMS5803,ReadBytesFromMS5803);

  26.   Delayms(20);


  27.   /*读取温度数据*/

  28. digitalTemperatureValue=ReadConversionFromMS5803(deviceAddress,COMMAND_CONVERTD2OSR4096,WriteCommandToMS5803,ReadBytesFromMS5803);


  29.   /*对温度进行一阶修正*/

  30.   int32_t dT;

  31.   int32_t temp;

  32.   dT=digitalTemperatureValue-tref*256;

  33.   temp=(int32_t)(2000+dT*tempsens/pow(2,23));



  34.   /*对压力进行一阶修正*/

  35.   int64_t off;

  36.   int64_t sens;

  37.   int32_t pres;

  38.   off=(int64_t)(offt1*pow(2,17)+(tco*dT)/pow(2,6));

  39.   sens=(int64_t)(senst1*pow(2,16)+(tcs*dT)/pow(2,7));

  40.   pres=(int32_t)((digitalPressureValue*sens/pow(2,21)-off)/pow(2,15));


  41.   /*对温度和压力进行二阶修正*/

  42.   int64_t ti=0;

  43.   int64_t offi=0;

  44.   int64_t sensi=0;

  45.   int64_t off2=0;

  46.   int64_t sens2=0;

  47.   if(temp<2000)

  48.   {

  49.     ti=(int64_t)(11*dT*dT/pow(2,35));

  50.     offi=(int64_t)(31*(temp-2000)*(temp-2000)/pow(2,3));

  51.     sensi=(int64_t)(63*(temp-2000)*(temp-2000)/pow(2,5));


  52.     off2=off-offi;

  53.     sens2=sens-sensi;


  54.     temp=temp-(int32_t)ti;

  55.     pres=(int32_t)((digitalPressureValue*sens2/pow(2,21)-off2)/pow(2,15));

  56.   }



  57.   if((-4000<=temp)&&(temp<=8500))

  58.   {

  59.     *pTemp=(float)temp/100.0;

  60.   }

  61.   if((1000<=pres)&&(pres<=190000))

  62.   {

  63.     *pPres=(float)pres/100.0;

  64.   }

  65. }
复制代码


STM32应用实例八.docx

489.69 KB, 下载次数: 16, 下载积分: 黑币 -5

STM32

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表