MRobot/User/device/bmp280_i2c.c
2025-04-27 19:59:24 +08:00

302 lines
7.5 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 "bmp280_i2c.h"
#include "bsp/i2c.h"
#define I2C_Handle BSP_I2C_GetHandle(BSP_I2C_BMP280)
/**
* @brief 读寄存器
* @param regAdd 寄存器开始地址
* @param pdata 存储数据的指针
* @param size 寄存器个数
* @retval 无
*/
void bmp280_readReg(uint8_t regAdd, uint8_t *pdata, uint8_t size) {
HAL_I2C_Mem_Read(I2C_Handle, BMP280_I2C_ADDR << 1, regAdd, I2C_MEMADD_SIZE_8BIT, pdata, size, 1000);
}
/**
* @brief 写1个寄存器
* @param regAdd 寄存器开始地址
* @param pdata 存储数据的指针
* @retval 0 写入成功
* 1 写入失败
*/
uint8_t bmp280_writeReg(uint8_t regAdd, uint8_t *pdata) {
if (HAL_I2C_Mem_Write(I2C_Handle, BMP280_I2C_ADDR << 1, regAdd, I2C_MEMADD_SIZE_8BIT, pdata, 1, 1000) == HAL_OK) {
return 0;
}
return 1;
}
/**
* @brief 读取设备物理id用于调试
* @param 无
* @retval 设备id
*/
uint8_t bmp280_get_id(void) {
uint8_t temp = 0;
bmp280_readReg(BMP280_ID, &temp, 1);
return temp;
}
/**
* @brief 重启设备
* @param 无
* @retval 0 重启成功
* 1 重启失败
*/
uint8_t bmp280_reset(void) {
uint8_t temp = 0xB6;
return bmp280_writeReg(BMP280_RESET, &temp);
}
/**
* @brief 获取设备状态
* @param 无
* @retval 0 空闲
* 1 正在测量或者正在复制
*/
uint8_t bmp280_getStatus(void) {
uint8_t temp = 0;
bmp280_readReg(BMP280_STATUS, &temp, 1);
return (temp & 0x09) ? 1 : 0;
}
/**
* @brief 工作模式设置推荐
* @param mode 0 睡眠模式
* 1 单次测量模式,测量完成后回到休眠模式
* 2 连续测量模式
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_setMode(uint8_t mode)
{
uint8_t temp=0;
bmp280_readReg(BMP280_CTRL_MEAS,&temp,1);
switch(mode)
{
case 0:
temp&=0xFC;
break;
case 1:
temp&=0xFC;
temp|=0x01;
break;
case 2:
temp&=0xFC;
temp|=0x03;
break;
default:
return 1;
}
return bmp280_writeReg(BMP280_CTRL_MEAS,&temp);
}
/**
* @brief 过采样设置
* @param mode temp&press 0 禁用
* 1 过采样×1
* 2 过采样×2
* 3 过采样×4
* .. .....
* 5 过采样×16
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_setOversampling(uint8_t osrs_p,uint8_t osrs_t)
{
uint8_t temp=0;
bmp280_readReg(BMP280_CTRL_MEAS,&temp,1);
temp&=0xE3;
osrs_p = osrs_p<<2;
osrs_p&= 0x1C;
temp|=osrs_p;
temp&=0x1F;
osrs_t = osrs_t<<5;
osrs_t&= 0xE0;
temp|=osrs_t;
return bmp280_writeReg(BMP280_CTRL_MEAS,&temp);
}
/**
* @brief 滤波器系数和采样间隔时间设置
* @param Standbyt 0 0.5ms filter 0 关闭滤波器
* 1 62.5ms 1 2
* 2 125ms 2 4
* 3 250ms 3 8
* 4 500ms 4 16
* 5 1000ms
* 6 2000ms
* 7 4000ms
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_setConfig(uint8_t Standbyt,uint8_t filter)
{
uint8_t temp=0;
temp = Standbyt<<5;
filter&=0x07;
filter=filter<<2;
temp|=filter;
return bmp280_writeReg(BMP280_CONFIG,&temp);
}
/**
* @brief 获取校准系数
* @param calib 储存系数的结构体
* @retval 无
*/
void bmp280_getCalibration(bmp280_calib *calib)
{
uint8_t buf[20];
bmp280_readReg(BMP280_DIGT,buf,6);
calib->dig_t1 =(uint16_t)(bmp280_msblsb_to_u16(buf[1], buf[0]));
calib->dig_t2 =(int16_t)(bmp280_msblsb_to_u16(buf[3], buf[2]));
calib->dig_t3 =(int16_t)(bmp280_msblsb_to_u16(buf[5], buf[4]));
bmp280_readReg(BMP280_DIGP,buf,18);
calib->dig_p1 = (uint16_t)(bmp280_msblsb_to_u16(buf[1], buf[0]));
calib->dig_p2 =(int16_t)(bmp280_msblsb_to_u16(buf[3], buf[2]));
calib->dig_p3 =(int16_t)(bmp280_msblsb_to_u16(buf[5], buf[4]));
calib->dig_p4 =(int16_t)(bmp280_msblsb_to_u16(buf[7], buf[6]));
calib->dig_p5 =(int16_t)(bmp280_msblsb_to_u16(buf[9], buf[8]));
calib->dig_p6 =(int16_t)(bmp280_msblsb_to_u16(buf[11], buf[10]));
calib->dig_p7 =(int16_t)(bmp280_msblsb_to_u16(buf[13], buf[12]));
calib->dig_p8 =(int16_t)(bmp280_msblsb_to_u16(buf[15], buf[14]));
calib->dig_p9 =(int16_t)(bmp280_msblsb_to_u16(buf[17], buf[16]));
}
/**
* @brief 获取温度
* @param calib 系数的结构体
* *temperature 温度值指针
* *t_fine 精细分辨率温度值指针
* @retval 无
*/
void bmp280_getTemperature(bmp280_calib *calib,double *temperature,int32_t *t_fine)
{
uint8_t buf[3];
uint32_t data_xlsb;
uint32_t data_lsb;
uint32_t data_msb;
int32_t uncomp_temperature;
double var1, var2;
bmp280_readReg(BMP280_TEMP,buf,3);
data_msb = (int32_t)buf[0] << 12;
data_lsb = (int32_t)buf[1] << 4;
data_xlsb = (int32_t)buf[2] >> 4;
uncomp_temperature = (int32_t)(data_msb | data_lsb | data_xlsb);
var1 = (((double) uncomp_temperature) / 16384.0 - ((double) calib->dig_t1) / 1024.0) *
((double) calib->dig_t2);
var2 =
((((double) uncomp_temperature) / 131072.0 - ((double) calib->dig_t1) / 8192.0) *
(((double) uncomp_temperature) / 131072.0 - ((double) calib->dig_t1) / 8192.0)) *
((double) calib->dig_t3);
*t_fine = (int32_t) (var1 + var2);
*temperature = (var1 + var2) / 5120.0;
}
/**
* @brief 获取气压
* @param calib 系数的结构体
* *pressure 气压值指针
* *t_fine 精细分辨率温度值指针
* @retval 无
*/
void bmp280_getPressure(bmp280_calib *calib,double *pressure,int32_t *t_fine)
{
uint8_t buf[3];
uint32_t data_xlsb;
uint32_t data_lsb;
uint32_t data_msb;
int32_t uncomp_pressure;
double var1, var2;
bmp280_readReg(BMP280_PRES,buf,3);
data_msb = (uint32_t)buf[0] << 12;
data_lsb = (uint32_t)buf[1] << 4;
data_xlsb = (uint32_t)buf[2] >> 4;
uncomp_pressure = (data_msb | data_lsb | data_xlsb);
var1 = ((double) *t_fine / 2.0) - 64000.0;
var2 = var1 * var1 * ((double) calib->dig_p6) / 32768.0;
var2 = var2 + var1 * ((double) calib->dig_p5) * 2.0;
var2 = (var2 / 4.0) + (((double) calib->dig_p4) * 65536.0);
var1 = (((double)calib->dig_p3) * var1 * var1 / 524288.0 + ((double)calib->dig_p2) * var1) /
524288.0;
var1 = (1.0 + var1 / 32768.0) * ((double) calib->dig_p1);
*pressure = 1048576.0 - (double)uncomp_pressure;
*pressure = (*pressure - (var2 / 4096.0)) * 6250.0 / var1;
var1 = ((double)calib->dig_p9) * *pressure * *pressure / 2147483648.0;
var2 = *pressure * ((double)calib->dig_p8) / 32768.0;
*pressure = *pressure + (var1 + var2 + ((double)calib->dig_p7)) / 16.0;
}
/**
* @brief 初始化
* @param *calib 系数的结构体指针
* @retval 0 设置成功
* 1 设置失败
*/
uint8_t bmp280_init(bmp280_calib *calib)
{
uint8_t rslt;
rslt = bmp280_get_id();
if(rslt == BMP2_CHIP_ID)
{
bmp280_getCalibration(calib);
rslt = bmp280_setOversampling(5,2);
if(rslt)
{
return 1;
}
rslt = bmp280_setConfig(0,4);
if(rslt)
{
return 1;
}
rslt = bmp280_setMode(2);
if(rslt)
{
return 1;
}
}
else
{
return 1;
}
return 0;
}
/**
* @brief 获取最终数据
* @param *calib 系数的结构体指针
* @retval 无
*/
void bmp280_getdata(bmp280_calib *calib,float *temperature,float *pressure)
{
double temp_T,temp_P;
int32_t t_fine;
bmp280_getTemperature(calib,&temp_T,&t_fine);
bmp280_getPressure(calib,&temp_P,&t_fine);
*temperature = (float)temp_T;
*pressure = (float)temp_P;
}