使用气压传感器MS5611获取温度数据和气压数据

描述

MS5611是一款由瑞士公司MEAS推出的高分辨率气压传感器。它具有以下特点:

接口:支持SPI和I²C总线接口。(通过PS脚来选择)

内部结构:包括高线性度的压力传感器和超低功耗的24位累加模数转换器(工厂校准系数)。

功能:提供精确的24位数字压力值和温度值,适用于高度计、温度计等功能。

尺寸:仅有5.0毫米×3.0毫米×1.0毫米的小尺寸,适合集成在移动设备中。

这款传感器采用领先的MEMS技术,具有高稳定性和非常低的压力信号滞后。它在移动高度计、气压计系统、自行车电脑、智能手机等领域有广泛的应用

准备工作

由于芯片上支持IIC通讯,因此我们打算使用STM32的硬件IIC,我的STM32为STM32F407。

我们打开CUBEMX,选择好我们的时钟还有其他设置之后,我们打开我们的硬件IIC

mems

并且我们打开串口来进行调试,我们选择IIC1,可以发现是PB6/PB7。

并且我们在USART.C文件中加入我们的串口重定向代码,方便我们使用printf函数

struct __FILE 
{ 
  int handle; 
}; 


struct __FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
  x = x; 
} 
//重定义fputc函数 
int fputc(int ch, struct __FILE *f)
{   
  while((USART1- >SR&0X40)==0);//循环发送,直到发送完毕   
  USART1- >DR = (unsigned char) ch;      
  return ch;
}

利用这串代码,我们就可以把我们的串口发送函数重定向到我们的printf函数上。

之后我们测试一下,我们的串口发送。

mems

可以看到串口重定向成功。

数据解释

mems

我们在MS5611的官方手册中可以看到,MS5611的数据主要由C1~C6这六个校准系数以及D1,D2两个数据组成。

mems

通过这些数据配合芯片手册计算方式我们可以计算出我们的传感器数值。

mems

我们在向MS5611发送数据转换命令的时候,模块会把对应的信号转换好之后存入PROM寄存器中,我们需要读取PROM的数据来读取这些数据,PROM的地址从0XA0~0XAE

代码编写

#define MS5611_I2C_ADDR 0xEE //PS拉高的地址
#define CMD_ADC_READ    0x00 //ADC转换开始
#define CMD_ADC_CONV_D1 0x40 //D1读取命令
#define CMD_ADC_CONV_D2 0x50 //D2读取命令
#define CMD_PROM_RD     0xA0 //PROM基地址


typedef struct {
    double temperature;//温度
    double pressure;//气压
    uint32_t D1;
    uint32_t D2;
    uint16_t C1;
    uint16_t C2;
    uint16_t C3;
    uint16_t C4;
    uint16_t C5;
    uint16_t C6;
} MS5611Data;

首先我们定义模块的命令宏定义以及我们的结构体用来存放我们的数据。

extern I2C_HandleTypeDef hi2c1;
void ReadMS5611Data(MS5611Data *ms5611Data);

其次定义我们的hi2c1句柄,由于这个句柄的实际定义是在i2c.h文件中,因此我们需要加上extern来修饰我们的变量

接着我们来定义我们的ReadMS5611Data函数,我们分步讲解。

HAL_I2C_Mem_Write(&hi2c1, MS5611_I2C_ADDR, CMD_ADC_CONV_D1, I2C_MEMADD_SIZE_8BIT, NULL, 0, 100);
    HAL_Delay(10);
    uint8_t buffer[3];
    HAL_I2C_Mem_Read(&hi2c1, MS5611_I2C_ADDR, CMD_ADC_READ, I2C_MEMADD_SIZE_8BIT, buffer, 3, 100);
    ms5611Data- >D1 = ((uint32_t)buffer[0] < < 16) | ((uint32_t)buffer[1] < < 8) | (uint32_t)buffer[2];

首先是利用HAL库的IIC写命令函数,我们向模块发送读取命令,

mems

由于D1,D2都是24个空间,因此我们的数据分3次读取,我们定义一个uint8_t buffer[3];分别存储三次数据

之后我们利用移位运算符,把我们的数据依次拼接到我们的D1数据上。
HAL_I2C_Mem_Write(&hi2c1, MS5611_I2C_ADDR, CMD_ADC_CONV_D2, I2C_MEMADD_SIZE_8BIT, NULL, 0, 100);
HAL_Delay(10);
HAL_I2C_Mem_Read(&hi2c1, MS5611_I2C_ADDR, CMD_ADC_READ, I2C_MEMADD_SIZE_8BIT, buffer, 3, 100);    
ms5611Data- >D2 = ((uint32_t)buffer[0] < < 16) | ((uint32_t)buffer[1] < < 8) | (uint32_t)buffer[2];

这部分也是同理,我们用这个方式获取D2的值。

uint8_t coef_data[2];
    for (int i = 1; i <= 6; i++) {
        HAL_I2C_Mem_Read(&hi2c1, MS5611_I2C_ADDR, CMD_PROM_RD + (i)*2, I2C_MEMADD_SIZE_8BIT, coef_data, 2, 100);
        if (i == 1) {
            ms5611Data- >C1 = (coef_data[0] < < 8) | coef_data[1];
        } else if (i == 2) {
            ms5611Data- >C2 = (coef_data[0] < < 8) | coef_data[1];
        } else if (i == 3) {
            ms5611Data- >C3 = (coef_data[0] < < 8) | coef_data[1];
        } else if (i == 4) {
            ms5611Data- >C4 = (coef_data[0] < < 8) | coef_data[1];
        } else if (i == 5) {
            ms5611Data- >C5 = (coef_data[0] < < 8) | coef_data[1];
        } else if (i == 6) {
            ms5611Data- >C6 = (coef_data[0] < < 8) | coef_data[1];
        }
    }

接着我们定义一个数据用来存储我们的校准系数,由于校准系数是存储在PORM上的

mems

所以我们需要用MS5611_I2C_ADDR, CMD_PROM_RD + (i)*2来确定我们的地址

我们把数据按照高8位低8位存储到校准系数中

int32_t dt = ms5611Data- >D2 - ((int32_t)ms5611Data- >C5 *256);
double temp = 2000+((double)dt/ 8388608)*ms5611Data- >C6;

接着我们按照手册中的方法计算我们的数据,需要注意的是,temp的类型最好选择是double型,否则dt/8388608(1<<23)可能会数据丢失。

同样的我们再用这种办法计算我们的气压值(手册上面都有)

int64_t off = ((int64_t)ms5611Data- >C2 * 65536) + ((int64_t)ms5611Data- >C4 * dt) / 128;
int64_t sens = ((int64_t)ms5611Data- >C1 < < 15) + (((int64_t)ms5611Data- >C3 * dt) / (1 < < 8));
double pressure = ((double)ms5611Data- >D1 * sens/2097152 - off) / (1 < < 15);

效果展示

mems

可以看到我们的气压数据打印出来是符合常理的。

mems

我们的温度数据也是正常显示的

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分