Quadcopter/User/BarometerDriver/spl06.c
2025-10-28 22:24:27 +08:00

335 lines
9.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "main.h"
#include "bsp/time.h"
#include "math.h"
#include "BarometerDriver/SPL06.h"
#include "BarometerDriver/user_iic.h"
SPL06 spl06;
SPL06_Calib_Param spl06_calib_param;
/***************************************************************************
* 函 数 名: spl06_write_reg
* 功能说明: IIC写
* 形 参: 无
* 返 回 值: 无
**************************************************************************/
uint8_t spl06_write_reg(uint8_t reg_addr,uint8_t reg_val)
{
IIC_Start();
IIC_Send_Byte((SP06_Advice_Address<<1)|0);//发送器件地址+写命令
if(IIC_Wait_Ack()) //等待应答
{
IIC_Stop();
return 1;
}
IIC_Send_Byte(reg_addr); //写寄存器地址
IIC_Wait_Ack(); //等待应答
IIC_Send_Byte(reg_val);//发送数据
if(IIC_Wait_Ack()) //等待ACK
{
IIC_Stop();
return 1;
}
IIC_Stop();
return 0;
// /*HAL库*/
// uint8_t status = 0;
//
// // 使用HAL库发送数据(器件地址+寄存器地址+数据)
// status = HAL_I2C_Mem_Write(&hi2c2,
// (SP06_Advice_Address << 1),
// reg_addr,
// I2C_MEMADD_SIZE_8BIT,
// &reg_val,
// 1,
// 100);
//
// return (status == HAL_OK) ? 0 : 1;
}
//IIC读SPL06寄存器
uint8_t spl06_read_reg(uint8_t reg_addr)
{
uint8_t res;
IIC_Start();
IIC_Send_Byte((SP06_Advice_Address<<1)|0);//发送器件地址+写命令
IIC_Wait_Ack(); //等待应答
IIC_Send_Byte(reg_addr); //写寄存器地址
IIC_Wait_Ack(); //等待应答
IIC_Start();
IIC_Send_Byte((SP06_Advice_Address<<1)|1);//发送器件地址+读命令
IIC_Wait_Ack(); //等待应答
res=IIC_Read_Byte(0);//读取数据,发送nACK
IIC_Stop(); //产生一个停止条件
return res;
// /*HAL库*/
// uint8_t reg_val = 0;
//
// HAL_I2C_Mem_Read(&hi2c2,
// (SP06_Advice_Address << 1),
// reg_addr,
// I2C_MEMADD_SIZE_8BIT,
// &reg_val,
// 1,
// 100);
//
// return reg_val;
}
//
void spl06_start(uint8_t mode)
{
spl06_write_reg(SP06_MEAS_CFG, mode);//测量模式配置
}
void spl06_config_temperature(uint8_t rate,uint8_t oversampling)
{
uint8_t data;
data = (1<<7)|rate|oversampling;
if(oversampling > TMP_PRC_8)//过采样次数大于EMPERATURE_RATE_8_TIMES应当允许数据被新的数据覆盖内部拥有气压和温度共32级的FIFO在大于8次也就是大于或等于16次过采样的时候需要被新的数据覆盖否则数据就会丢失
{
uint8_t data;
data = spl06_read_reg(SP06_CFG_REG);//读取原寄存器值
data |= SPL06_CFG_T_SHIFT;//P-SHIFT位置1
spl06_write_reg(SP06_CFG_REG, data);//重新写回寄存器
}
switch(oversampling)
{
case TMP_PRC_1:
spl06.i32kT = 524288;
break;
case TMP_PRC_2:
spl06.i32kT = 1572864;
break;
case TMP_PRC_4:
spl06.i32kT = 3670016;
break;
case TMP_PRC_8:
spl06.i32kT = 7864320;
break;
case TMP_PRC_16:
spl06.i32kT = 253952;
break;
case TMP_PRC_32:
spl06.i32kT = 516096;
break;
case TMP_PRC_64:
spl06.i32kT = 1040384;
break;
case TMP_PRC_128:
spl06.i32kT = 2088960;
break;
}
spl06_write_reg(SP06_TMP_CFG, data);//重新写回寄存器
}
void spl06_config_pressure(uint8_t rate,uint8_t oversampling)//设置补偿系数及采样速率
{
uint8_t data;
data = rate|oversampling;
if(oversampling > PM_PRC_8)//过采样次数大于EMPERATURE_RATE_8_TIMES应当允许数据被新的数据覆盖内部拥有气压和温度共32级的FIFO在大于8次也就是大于或等于16次过采样的时候需要被新的数据覆盖否则数据就会丢失
{
uint8_t data;
data = spl06_read_reg(SP06_CFG_REG);//读取原寄存器值
data |= SPL06_CFG_P_SHIFT;//P-SHIFT位置1
spl06_write_reg(SP06_CFG_REG, data);//重新写回寄存器
}
switch(oversampling)
{
case PM_PRC_1:
spl06.i32kP = 524288;
break;
case PM_PRC_2:
spl06.i32kP = 1572864;
break;
case PM_PRC_4:
spl06.i32kP = 3670016;
break;
case PM_PRC_8:
spl06.i32kP = 7864320;
break;
case PM_PRC_16:
spl06.i32kP = 253952;
break;
case PM_PRC_32:
spl06.i32kP = 516096;
break;
case PM_PRC_64:
spl06.i32kP = 1040384;
break;
case PM_PRC_128:
spl06.i32kP = 2088960;
break;
}
spl06_write_reg(SP06_PSR_CFG, data); //写入配置
}
int32_t spl06_get_pressure_adc(void)//获取压力ADC值
{
uint8_t buf[3];
int32_t adc;
buf[0] = spl06_read_reg(SP06_PSR_B2);
buf[1] = spl06_read_reg(SP06_PSR_B1);
buf[2] = spl06_read_reg(SP06_PSR_B0);
adc = (int32_t)buf[0]<<16 | (int32_t)buf[1]<<8 | (int32_t)buf[2];
adc = (adc&0x800000)?(0xFF000000|adc):adc;
return adc;
}
int32_t spl06_get_temperature_adc(void)//获取温度ADC值
{
uint8_t buf[3];
int32_t adc;
buf[0] = spl06_read_reg(SP06_TMP_B2);
buf[1] = spl06_read_reg(SP06_TMP_B1);
buf[2] = spl06_read_reg(SP06_TMP_B0);
adc = (int32_t)buf[0]<<16 | (int32_t)buf[1]<<8 | (int32_t)buf[2];
adc = (adc&0x800000)?(0xFF000000|adc):adc;
return adc;
}
uint8_t SPL06_Update(int32_t *Temp,int32_t *Press)//获取并计算出温度值、气压值
{
float Praw_src=0,Traw_src=0;
float qua2=0, qua3=0;
Traw_src = spl06_get_temperature_adc()/(float)spl06.i32kT;
Praw_src = spl06_get_pressure_adc()/(float)spl06.i32kP ;
//计算温度
*Temp = 0.5*spl06_calib_param.c0 + spl06_calib_param.c1* Traw_src;
//计算气压
qua2 = spl06_calib_param.c10 + Praw_src * (spl06_calib_param.c20 + Praw_src*spl06_calib_param.c30);
qua3 = Traw_src * Praw_src * (spl06_calib_param.c11 + Praw_src * spl06_calib_param.c21);
*Press = spl06_calib_param.c00 + Praw_src * qua2 + Traw_src * spl06_calib_param.c01 + qua3;
return 0;
}
//获取传感器数据就位状态,传感器就绪状态
uint8_t spl06_get_measure_status(void)
{
return spl06_read_reg(SP06_MEAS_CFG);
}
//设置读取模式+读取方式
void spl06_set_measure_mode(uint8_t mode) //参数为模式值
{
spl06_write_reg(SP06_MEAS_CFG, mode);
}
//启动命令模式读取温度值
void spl06_start_temperature(void)
{
spl06_write_reg(SP06_MEAS_CFG, MEAS_CTRL_TempMeasure);
}
//启动命令模式读取气压值
void spl06_start_pressure(void)
{
spl06_write_reg(SP06_MEAS_CFG, MEAS_CTRL_PressMeasure);
}
//进入待机模式,进入后停止采集数据直到再次切换模式
void spl06_enter_standby(void)
{
spl06_write_reg(SP06_MEAS_CFG, MEAS_CTRL_Standby);
}
void spl06_get_calib_param()
{
unsigned long h;
unsigned long m;
unsigned long l;
h = spl06_read_reg(0x10);
l = spl06_read_reg(0x11);
spl06_calib_param.c0 = (int16_t)h<<4 | l>>4;
spl06_calib_param.c0 = (spl06_calib_param.c0&0x0800)?(0xF000|spl06_calib_param.c0):spl06_calib_param.c0;
h = spl06_read_reg(0x11);
l = spl06_read_reg(0x12);
spl06_calib_param.c1 = (int16_t)(h&0x0F)<<8 | l;
spl06_calib_param.c1 = (spl06_calib_param.c1&0x0800)?(0xF000|spl06_calib_param.c1):spl06_calib_param.c1;
h = spl06_read_reg(0x13);
m = spl06_read_reg(0x14);
l = spl06_read_reg(0x15);
spl06_calib_param.c00 = (int32_t)h<<12 | (int32_t)m<<4 | (int32_t)l>>4;
spl06_calib_param.c00 = (spl06_calib_param.c00&0x080000)?(0xFFF00000|spl06_calib_param.c00):spl06_calib_param.c00;
h = spl06_read_reg(0x15);
m = spl06_read_reg(0x16);
l = spl06_read_reg(0x17);
spl06_calib_param.c10 = (int32_t)h<<16 | (int32_t)m<<8 | l;
spl06_calib_param.c10 = (spl06_calib_param.c10&0x080000)?(0xFFF00000|spl06_calib_param.c10):spl06_calib_param.c10;
h = spl06_read_reg(0x18);
l = spl06_read_reg(0x19);
spl06_calib_param.c01 = (int16_t)h<<8 | l;
h = spl06_read_reg(0x1A);
l = spl06_read_reg(0x1B);
spl06_calib_param.c11 = (int16_t)h<<8 | l;
h = spl06_read_reg(0x1C);
l = spl06_read_reg(0x1D);
spl06_calib_param.c20 = (int16_t)h<<8 | l;
h = spl06_read_reg(0x1E);
l = spl06_read_reg(0x1F);
spl06_calib_param.c21 = (int16_t)h<<8 | l;
h = spl06_read_reg(0x20);
l = spl06_read_reg(0x21);
spl06_calib_param.c30 = (int16_t)h<<8 | l;
}
uint8_t SPL06_Init(void)
{
uint8_t spl06_start_status;
if(spl06_write_reg(SP06_RESET,0x89))
{
return 1;
}
BSP_TIME_Delay(100); //复位后系数准备好需要至少40ms
do
spl06_start_status = spl06_get_measure_status(); //读取气压计启动状态
while((spl06_start_status&MEAS_COEF_RDY)!=MEAS_COEF_RDY);
//读取内部校准值
spl06_get_calib_param();
do
spl06_start_status = spl06_get_measure_status();//读取气压计启动状态
while((spl06_start_status&MEAS_SENSOR_RDY)!= MEAS_SENSOR_RDY);
spl06.chip_id = spl06_read_reg(SP06_ID);
if((spl06.chip_id & 0xf0) != SP06_COEF )
{
return 2;
}
spl06_config_pressure(PM_RATE_128,PM_PRC_8);
spl06_config_temperature(TMP_RATE_128,TMP_PRC_8);
spl06_start(MEAS_CTRL_ContinuousPressTemp); //启动连续的气压温度测量
return 0;
}
//通过气压计算高度
int32_t SPL06_CaculateHeight(int32_t GasPress)
{
int32_t Altitude=0;
Altitude =(44330.0 *(1.0-pow((float)(GasPress) / 101325.0,1.0/5.255)))*1000;//单位mm
return Altitude;
}