#include "iic_bmp388.h"
#include "iic.h"
#include "delay.h"
#include "app.h"
#include <math.h>
/* Private define ------------------------------------------------------------*/
//IIC地址,SDO接地为0x76,接VCC地址为0x77
#define BMP388_Addr 0x76
#define Concat_Bytes(msb, lsb) (((uint16_t)msb << 8) | (uint16_t)lsb)
/* Public variables ----------------------------------------------------------*/
struct bmp3_calib_data calib_data;
struct bmp3_uncomp_data uncomp_data;
struct bmp3_data comp_data;
/* Public function -----------------------------------------------------------*/
//读取未修正的气压和温度信息
uint8_t get_PandT()
{
uint8_t reg_data[6]={0};
uint8_t time = 0 ,status = 0;
while(!((status&0x40)&&(status&0x20))) //查询数据是否准备完毕 0 1 1 0 0000
{
DS.sensor_iic[DS.iic.read_index].failed_code = IIC_WriteRead(BMP388_Addr << 1, 0x03, 0, 0, 1, &status, 0);
delay_ms(1);
time++;
if(time >= 5)
{
if(DS.sensor_iic[DS.iic.read_index].continue_failed_cnt < 0xFF)
DS.sensor_iic[DS.iic.read_index].continue_failed_cnt++;
if(DS.sensor_iic[DS.iic.read_index].total_failed_cnt < 0xFFFF)
DS.sensor_iic[DS.iic.read_index].total_failed_cnt++;
DS.sensor_iic[DS.iic.read_index].failed_code = 1;
if(DS.sensor_iic[DS.iic.read_index].continue_failed_cnt >= 5)
{
DS.sensor_iic[DS.iic.read_index].value.flts[0] = Var.iic_sensor[DS.iic.read_index].invalid_value;
DS.sensor_iic[DS.iic.read_index].value.flts[1] = Var.iic_sensor[DS.iic.read_index].invalid_value;
}
return 1;
}
}
DS.sensor_iic[DS.iic.read_index].failed_code = IIC_WriteRead(BMP388_Addr << 1, 0x04, 0, 0, 6, reg_data, 0);
//数据合成
uncomp_data.pressure = reg_data[2]<<16 | reg_data[1]<<8 | reg_data[0];
uncomp_data.temperature = reg_data[5]<<16 | reg_data[4]<<8 | reg_data[3];
DS.sensor_iic[DS.iic.read_index].continue_failed_cnt = 0;
DS.sensor_iic[DS.iic.read_index].failed_code = 0;
return 0;
}
//读取修正系数
void get_calib_data()
{
uint8_t reg_data[21] = {0};
if(IIC_WriteRead(BMP388_Addr << 1, 0x31, 0, 0, 21, reg_data, 0))
return;
//根据数据手册的数据类型转换
calib_data.par_t1 = Concat_Bytes(reg_data[1], reg_data[0]);
calib_data.par_t2 = Concat_Bytes(reg_data[3], reg_data[2]);
calib_data.par_t3 = (int8_t)reg_data[4];
calib_data.par_p1 = (int16_t)Concat_Bytes(reg_data[6], reg_data[5]);
calib_data.par_p2 = (int16_t)Concat_Bytes(reg_data[8], reg_data[7]);
calib_data.par_p3 = (int8_t)reg_data[9];
calib_data.par_p4 = (int8_t)reg_data[10];
calib_data.par_p5 = Concat_Bytes(reg_data[12], reg_data[11]);
calib_data.par_p6 = Concat_Bytes(reg_data[14], reg_data[13]);
calib_data.par_p7 = (int8_t)reg_data[15];
calib_data.par_p8 = (int8_t)reg_data[16];
calib_data.par_p9 = (int16_t)Concat_Bytes(reg_data[18], reg_data[17]);
calib_data.par_p10 = (int8_t)reg_data[19];
calib_data.par_p11 = (int8_t)reg_data[20];
}
//修正温度
void compensate_temperature()
{
uint64_t partial_data1;
uint64_t partial_data2;
uint64_t partial_data3;
int64_t partial_data4;
int64_t partial_data5;
int64_t partial_data6;
int64_t comp_temp;
partial_data1 = uncomp_data.temperature - (256 * calib_data.par_t1);
partial_data2 = calib_data.par_t2 * partial_data1;
partial_data3 = partial_data1 * partial_data1;
partial_data4 = (int64_t)partial_data3 * calib_data.par_t3;
partial_data5 = ((int64_t)(partial_data2 * 262144) + partial_data4);
partial_data6 = partial_data5 / 4294967296;
calib_data.t_lin = partial_data6; /* 存储这个data6为t_lin因为计算气压要用到 */
comp_temp = (int64_t)((partial_data6 * 25) / 16384);
comp_data.temperature = comp_temp;
}
//修正气压
void compensate_pressure()
{
int64_t partial_data1;
int64_t partial_data2;
int64_t partial_data3;
int64_t partial_data4;
int64_t partial_data5;
int64_t partial_data6;
int64_t offset;
int64_t sensitivity;
uint64_t comp_press;
partial_data1 = calib_data.t_lin * calib_data.t_lin;
partial_data2 = partial_data1 / 64;
partial_data3 = (partial_data2 * calib_data.t_lin) / 256;
partial_data4 = (calib_data.par_p8 * partial_data3) / 32;
partial_data5 = (calib_data.par_p7 * partial_data1) * 16;
partial_data6 = (calib_data.par_p6 * calib_data.t_lin) * 4194304;
offset = (calib_data.par_p5 * 140737488355328) + partial_data4 + partial_data5 + partial_data6;
partial_data2 = (calib_data.par_p4 * partial_data3) / 32;
partial_data4 = (calib_data.par_p3 * partial_data1) * 4;
partial_data5 = (calib_data.par_p2 - 16384) * calib_data.t_lin * 2097152;
sensitivity = ((calib_data.par_p1 - 16384) * 70368744177664) + partial_data2 + partial_data4 + partial_data5;
partial_data1 = (sensitivity / 16777216) * uncomp_data.pressure;
partial_data2 = calib_data.par_p10 * calib_data.t_lin;
partial_data3 = partial_data2 + (65536 * calib_data.par_p9);
partial_data4 = (partial_data3 * uncomp_data.pressure) / 8192;
partial_data5 = (partial_data4 * uncomp_data.pressure) / 512;
partial_data6 = (int64_t)((uint64_t)uncomp_data.pressure * (uint64_t)uncomp_data.pressure);
partial_data2 = (calib_data.par_p11 * partial_data6) / 65536;
partial_data3 = (partial_data2 * uncomp_data.pressure) / 128;
partial_data4 = (offset / 4) + partial_data1 + partial_data5 + partial_data3;
comp_press = (((uint64_t)partial_data4 * 25) / (uint64_t)1099511627776);
comp_data.pressure = comp_press;
}
//BMP388初始化
uint8_t BMP388_Init()
{
uint8_t tx_buff[1], rx_buff[1];
if(IIC_WriteRead(BMP388_Addr << 1, 0x00, 0, 0, 1, rx_buff, 0)) //读取芯片ID
return 1;
if(rx_buff[0] != 0x50) //验证芯片ID
return 1;
get_calib_data(); //读取补偿系数
while(1)
{
if(IIC_WriteRead(BMP388_Addr << 1, 0x00, 0, 0, 1, rx_buff, 0))
return 1;
if(rx_buff[0] & 0x10)
break;
delay_ms(3);
}
tx_buff[0] = 0xb6;
IIC_WriteRead(BMP388_Addr << 1, 0x7e, 1, tx_buff, 0, 0, 0); //写重置指令,重置全部寄存器
delay_ms(5);
IIC_WriteRead(BMP388_Addr << 1, 0x02, 0, 0, 1, rx_buff, 0);
if(rx_buff[0] & 0x07) //查看错误指示寄存器,有错误返回1
return 1;
tx_buff[0] = 0x00;
IIC_WriteRead(BMP388_Addr << 1, 0x1c, 1, tx_buff, 0, 0, 0); //设置设置温度过采样*1 气压过采样*1 00 000 000
tx_buff[0] = 0x04;
IIC_WriteRead(BMP388_Addr << 1, 0x1f, 1, tx_buff, 0, 0, 0); //设置滤波系数2 0000 010 0
tx_buff[0] = 0x01;
IIC_WriteRead(BMP388_Addr << 1, 0x1d, 1, tx_buff, 0, 0, 0); //设置输出分频系数,请按照相关公式计算得出要写的值
tx_buff[0] = 0x33;
IIC_WriteRead(BMP388_Addr << 1, 0x1b, 1, tx_buff, 0, 0, 0); //使能气压和温度采样, 启动采样
return 0;
}
//获得正确的值
void BMP388_Get_PaT()
{
if(!get_PandT())
{
compensate_temperature();
compensate_pressure();
DS.sensor_iic[DS.iic.read_index].value.flts[0] = comp_data.pressure/100.0; //大气压值
//DS.sensor_iic[DS.iic.read_index].value.flts[1] = comp_data.temperature/100.0; //温度值
DS.sensor_iic[DS.iic.read_index].value.flts[1] = 44300*(1-pow(DS.sensor_iic[DS.iic.read_index].value.flts[0]/101325, 1/5.256));//高度值
}
DS.iic.read_index++;
if(DS.iic.read_index >= IIC_MAX_NUM)
DS.iic.read_index = 0;
}
void BMP388_ON()
{
uint8_t tx_buff[1];
tx_buff[0] = 0x33;
IIC_WriteRead(BMP388_Addr << 1, 0x1b, 1, tx_buff, 0, 0, 0); //启动传输 00 11 00 11
}
void BMP388_OFF()
{
uint8_t tx_buff[1];
tx_buff[0] = 0x03;
IIC_WriteRead(BMP388_Addr << 1, 0x1b, 1, tx_buff, 0, 0, 0); //进入睡眠 00 00 00 11
}
无线传感器
● 内置电池或外接5V电源供电
● 多种传感器和通讯接口:I2C、UART、RS485
● 支持WIFI、4G、Lora等多种无线通讯方式
● 支持串口固件升级
【传感器 ● 单片机项目定制开发】 |