KT24-1110_65E-HA-651B/apps/common/device/bmp280/bmp280.c

405 lines
16 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +00:00
#include "app_config.h"
#include "asm/clock.h"
#include "system/timer.h"
#include "bmp280.h"
#include "asm/cpu.h"
#include "generic/typedef.h"
#include "generic/gpio.h"
#if defined(TCFG_BMP280_DEV_ENABLE) && TCFG_BMP280_DEV_ENABLE
#undef LOG_TAG_CONST
#define LOG_TAG "[bmp280]"
#define LOG_ERROR_ENABLE
#define LOG_INFO_ENABLE
#include "debug.h"
struct _bmp280_dev_platform_data *bmp280_iic_info;
#if TCFG_BMP280_USER_IIC_TYPE
#define iic_init(iic) hw_iic_init(iic)
#define iic_uninit(iic) hw_iic_uninit(iic)
#define iic_start(iic) hw_iic_start(iic)
#define iic_stop(iic) hw_iic_stop(iic)
#define iic_tx_byte(iic, byte) hw_iic_tx_byte(iic, byte)
#define iic_rx_byte(iic, ack) hw_iic_rx_byte(iic, ack)
#define iic_read_buf(iic, buf, len) hw_iic_read_buf(iic, buf, len)
#define iic_write_buf(iic, buf, len) hw_iic_write_buf(iic, buf, len)
#define iic_suspend(iic) hw_iic_suspend(iic)
#define iic_resume(iic) hw_iic_resume(iic)
#else
#define iic_init(iic) soft_iic_init(iic)
#define iic_uninit(iic) soft_iic_uninit(iic)
#define iic_start(iic) soft_iic_start(iic)
#define iic_stop(iic) soft_iic_stop(iic)
#define iic_tx_byte(iic, byte) soft_iic_tx_byte(iic, byte)
#define iic_rx_byte(iic, ack) soft_iic_rx_byte(iic, ack)
#define iic_read_buf(iic, buf, len) soft_iic_read_buf(iic, buf, len)
#define iic_write_buf(iic, buf, len) soft_iic_write_buf(iic, buf, len)
#define iic_suspend(iic) soft_iic_suspend(iic)
#define iic_resume(iic) soft_iic_resume(iic)
#endif
/* extern void delay(unsigned int cnt);//eeprom */
extern void delay_2ms(int cnt);//fm
static bool bmp280_read_buf(u8 reg, u8 *buf, u8 len)
{
iic_start(bmp280_iic_info->iic_hdl);
if (0 == iic_tx_byte(bmp280_iic_info->iic_hdl, BMP280_I2C_ADDR << 1 | 0)) {
iic_stop(bmp280_iic_info->iic_hdl);
log_error("bmp280 read fail1!\n");
return false;
}
delay_2ms(bmp280_iic_info->iic_delay);
if (0 == iic_tx_byte(bmp280_iic_info->iic_hdl, reg)) {
iic_stop(bmp280_iic_info->iic_hdl);
log_error("bmp280 read fail2!\n");
return false;
}
delay_2ms(bmp280_iic_info->iic_delay);
iic_start(bmp280_iic_info->iic_hdl);
if (0 == iic_tx_byte(bmp280_iic_info->iic_hdl, BMP280_I2C_ADDR << 1 | 1)) {
iic_stop(bmp280_iic_info->iic_hdl);
log_error("bmp280 read fail3!\n");
return false;
}
for (u8 i = 0; i < len - 1; i++) {
buf[i] = iic_rx_byte(bmp280_iic_info->iic_hdl, 1);
delay_2ms(bmp280_iic_info->iic_delay);
}
buf[len - 1] = iic_rx_byte(bmp280_iic_info->iic_hdl, 0);
iic_stop(bmp280_iic_info->iic_hdl);
delay_2ms(bmp280_iic_info->iic_delay);
return true;
}
static bool bmp280_write_byte(u8 reg, u8 data)
{
iic_start(bmp280_iic_info->iic_hdl);
if (0 == iic_tx_byte(bmp280_iic_info->iic_hdl, BMP280_I2C_ADDR << 1)) {
iic_stop(bmp280_iic_info->iic_hdl);
log_error("bmp280 write fail1!\n");
return false;
}
delay_2ms(bmp280_iic_info->iic_delay);
if (0 == iic_tx_byte(bmp280_iic_info->iic_hdl, reg)) {
iic_stop(bmp280_iic_info->iic_hdl);
log_error("bmp280 write fail2!\n");
return false;
}
delay_2ms(bmp280_iic_info->iic_delay);
if (0 == iic_tx_byte(bmp280_iic_info->iic_hdl, data)) {
iic_stop(bmp280_iic_info->iic_hdl);
log_error("bmp280 write fail3!\n");
return false;
}
iic_stop(bmp280_iic_info->iic_hdl);
delay_2ms(bmp280_iic_info->iic_delay);
return true;
}
//设置BMP过采样因子 MODE
//BMP280_SLEEP_MODE||BMP280_FORCED_MODE||BMP280_NORMAL_MODE
bool bmp280_set_temoversamp(bmp_oversample_mode *oversample_mode)
{
u8 regtmp;
regtmp = ((oversample_mode->t_osample) << 5) |
((oversample_mode->p_osample) << 2) |
((oversample_mode)->workmode);
/* log_info("init reg:%x",regtmp); */
return bmp280_write_byte(BMP280_CTRLMEAS_REG, regtmp);
}
//设置保持时间和滤波器分频因子
bool bmp280_set_standby_filter(bmp_config *bmp_config)
{
u8 regtmp;
regtmp = ((bmp_config->t_sb) << 5) |
((bmp_config->filter_coefficient) << 2) |
((bmp_config->spi_en));
/* log_info("init config reg:%x",regtmp); */
return bmp280_write_byte(BMP280_CONFIG_REG, regtmp);
}
//设置bmp280工作模式
void bmp280_set_work_mode(BMP280_WORK_MODE workmode)
{
u8 ctrl_maes_data = 0;
bmp280_read_buf(BMP280_CTRLMEAS_REG, &ctrl_maes_data, 1);
/* log_info("old ctrl_maes_data:%x ",ctrl_maes_data); */
ctrl_maes_data &= ~(BIT(1) | BIT(0));
ctrl_maes_data += (workmode << 0);
/* log_info("nem ctrl_maes_data:%x ",ctrl_maes_data); */
bmp280_write_byte(BMP280_CTRLMEAS_REG, ctrl_maes_data);
}
//bmp280 复位
bool bmp280_reset() //return 1:ok; 0:fail
{
return bmp280_write_byte(BMP280_RESET_REG, BMP280_RESET_VALUE);
}
bmp280_params bmp280_par;
bool bmp280_init(void *priv)
{
u8 bmp280_id;
if (priv == NULL) {
log_info("bmp280 init fail(no priv)\n");
return false;
}
bmp280_iic_info = (struct _bmp280_dev_platform_data *)priv;
if (bmp280_read_buf(BMP280_CHIPID_REG, &bmp280_id, 1)) {
log_info("bmp280 id:%x", bmp280_id);
} else {
log_error("read bmp280 id fail!");
return false;
}
/********************读矫正参数*********************/
u8 temp[24] = {0};
bmp280_read_buf(BMP280_DIG_T1_LSB_REG, temp, 24);
//温度传感器的矫正值
bmp280_par.t1 = (((u16)temp[1]) << 8) + temp[0];
bmp280_par.t2 = (temp[3] << 8) + temp[2];
bmp280_par.t3 = (temp[5] << 8) + temp[4];
//大气压传感器的矫正值
bmp280_par.p1 = (((u16)temp[7]) << 8) + temp[6];
bmp280_par.p2 = (temp[9] << 8) + temp[8];
bmp280_par.p3 = (temp[11] << 8) + temp[10];
bmp280_par.p4 = (temp[13] << 8) + temp[12];
bmp280_par.p5 = (temp[15] << 8) + temp[14];
bmp280_par.p6 = (temp[17] << 8) + temp[16];
bmp280_par.p7 = (temp[19] << 8) + temp[18];
bmp280_par.p8 = (temp[21] << 8) + temp[20];
bmp280_par.p9 = (temp[23] << 8) + temp[22];
/* log_info("%d,%d,%d;%d,%d,%d,%d,%d,%d,%d,%d,%d",bmp280_par.t1,bmp280_par.t2,bmp280_par.t3,bmp280_par.p1,bmp280_par.p2,bmp280_par.p3,bmp280_par.p4,bmp280_par.p5,bmp280_par.p6,bmp280_par.p7,bmp280_par.p8,bmp280_par.p9); */
/******************************************************/
if (!(bmp280_write_byte(BMP280_RESET_REG, BMP280_RESET_VALUE))) { //往复位寄存器写入给定值
log_error("bmp280 reset error!\n");
return false;
}
bmp_config bmp_configstr;
bmp_configstr.t_sb = BMP280_T_SB1;
bmp_configstr.filter_coefficient = BMP280_FILTER_MODE_4;
bmp_configstr.spi_en = DISABLE;
if (!(bmp280_set_standby_filter(&bmp_configstr))) {
log_error("bmp280 init mode error!\n");
return false;
}
bmp_oversample_mode bmp_oversample_modestr;
bmp_oversample_modestr.t_osample = BMP280_T_MODE_1;
bmp_oversample_modestr.p_osample = BMP280_P_MODE_3;
bmp_oversample_modestr.workmode = BMP280_NORMAL_MODE;
if (!(bmp280_set_temoversamp(&bmp_oversample_modestr))) {
log_error("bmp280 init mode error!\n");
return false;
}
return true;
}
/*****************算法*******************/
/************计算补偿值***************/
s32 t_fine; //用于计算补偿
#if USE_FIXED_POINT_COMPENSATE //使用定点补偿
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
// t_fine carries fine temperature as global value
static s32 bmp280_compensate_t_int32(s32 adc_T)
{
s32 var1, var2, T;
var1 = (((adc_T >> 3) - ((s32)bmp280_par.t1 << 1)) * ((s32)bmp280_par.t2)) >> 11;
var2 = (((((adc_T >> 4) - ((s32)bmp280_par.t1)) * ((adc_T >> 4) - ((s32)bmp280_par.t1))) >> 12) * ((s32)bmp280_par.t3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
static u32 bmp280_compensate_p_int64(s32 adc_P)
{
s64 var1, var2, p;
var1 = ((s64)t_fine) - 128000;
var2 = var1 * var1 * (s64)bmp280_par.p6;
var2 = var2 + ((var1 * (s64)bmp280_par.p5) << 17);
var2 = var2 + (((s64)bmp280_par.p4) << 35);
var1 = ((var1 * var1 * (s64)bmp280_par.p3) >> 8) + ((var1 * (s64)bmp280_par.p2) << 12);
var1 = (((((s64)1) << 47) + var1)) * ((s64)bmp280_par.p1) >> 33;
if (var1 == 0) {
return 0; // avoid exception caused by division by zero
}
p = 1048576 - adc_P;
p = (((p << 31) - var2) * 3125) / var1;
var1 = (((s64)bmp280_par.p9) * (p >> 13) * (p >> 13)) >> 25;
var2 = (((s64)bmp280_par.p8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((s64)bmp280_par.p7) << 4);
return (u32)p;
}
#else //使用浮点补偿
// Returns temperature in DegC, double precision. Output value of “51.23” equals 51.23 DegC.
// t_fine carries fine temperature as global value
static double bmp280_compensate_t_double(s32 adc_T)
{
double var1, var2, T;
var1 = (((double)adc_T) / 16384.0 - ((double)bmp280_par.t1) / 1024.0) * ((double)bmp280_par.t2);
var2 = ((((double)adc_T) / 131072.0 - ((double)bmp280_par.t1) / 8192.0) * (((double)adc_T) / 131072.0 - ((double) bmp280_par.t1) / 8192.0)) * ((double)bmp280_par.t3);
t_fine = (s32)(var1 + var2);
T = (var1 + var2) / 5120.0;
return T;
}
// Returns pressure in Pa as double. Output value of “96386.2” equals 96386.2 Pa = 963.862 hPa
static double bmp280_compensate_p_double(s32 adc_P)
{
double var1, var2, p;
var1 = ((double)t_fine / 2.0) - 64000.0;
var2 = var1 * var1 * ((double)bmp280_par.p6) / 32768.0;
var2 = var2 + var1 * ((double)bmp280_par.p5) * 2.0;
var2 = (var2 / 4.0) + (((double)bmp280_par.p4) * 65536.0);
var1 = (((double)bmp280_par.p3) * var1 * var1 / 524288.0 + ((double)bmp280_par.p2) * var1) / 524288.0;
var1 = (1.0 + var1 / 32768.0) * ((double)bmp280_par.p1);
if (var1 == 0.0) {
return 0; // avoid exception caused by division by zero
}
p = 1048576.0 - (double)adc_P;
p = (p - (var2 / 4096.0)) * 6250.0 / var1;
var1 = ((double)bmp280_par.p9) * p * p / 2147483648.0;
var2 = p * ((double)bmp280_par.p8) / 32768.0;
p = p + (var1 + var2 + ((double)bmp280_par.p7)) / 16.0;
return p;
}
#endif
//获取BMP当前状态
//status_flag = BMP280_MEASURING
// BMP280_IM_UPDATE
static u8 bmp280_getstatus(u8 status_flag)
{
u8 flag;
bmp280_read_buf(BMP280_STATUS_REG, &flag, 1);
if (flag & status_flag) {
return 1;
} else {
return 0;
}
}
//温度值-℃(实际值的100倍(定点法)或实际值(浮点法))
static bmp_temperature_data bmp280_get_temperature(void)
{
u8 tem_data[3] = {0};
long signed bit32;
bmp280_read_buf(BMP280_TEMPERATURE_MSB_REG, tem_data, 3);
bit32 = ((long)(tem_data[0] << 12)) | ((long)(tem_data[1] << 4)) | (tem_data[2] >> 4);
/* log_info("tembit32:%ld",bit32); */
#if USE_FIXED_POINT_COMPENSATE //使用定点补偿
return bmp280_compensate_t_int32(bit32);
#else //使用浮点补偿
return bmp280_compensate_t_double(bit32);
#endif
}
//获取大气压值-Pa(实际值的100倍(定点法)或实际值(浮点法))
static bmp_pressure_data bmp280_get_pressure(void)
{
u8 tem_data[3] = {0};
long signed bit32;
bmp280_read_buf(BMP280_PRESSURE_MSB_REG, tem_data, 3);
bit32 = ((long)(tem_data[0] << 12)) | ((long)(tem_data[1] << 4)) | (tem_data[2] >> 4);
/* log_info("prebit32:%ld,t_fine:%d",bit32,t_fine); */
#if USE_FIXED_POINT_COMPENSATE //使用定点补偿
u32 pressure = bmp280_compensate_p_int64(bit32);
pressure = pressure * 100 / 256;
#else //使用浮点补偿
double pressure = bmp280_compensate_p_double(bit32);
#endif
return pressure;
}
/*
* BMP280被设置为normal mode时
* 使
* (100()())
*/
void bmp280_get_temperature_and_pressure(bmp_temperature_data *temperature, bmp_pressure_data *pressure)
{
while (bmp280_getstatus(BMP280_MEASURING));
while (bmp280_getstatus(BMP280_IM_UPDATE));
*temperature = bmp280_get_temperature(); //必须先读温度再度气压
*pressure = bmp280_get_pressure();
}
/**
* BMP280被设置为forced mode时
* 使
* (100()())
*/
void bmp280_forced_mode_get_temperature_and_pressure(bmp_temperature_data *temperature, bmp_pressure_data *pressure)
{
bmp280_set_work_mode(BMP280_FORCED_MODE);
bmp280_get_temperature_and_pressure(temperature, pressure);
}
//计算高度, 返回海拔高度: (m)
#include "math.h"
#define SEA_LEVEL_PRESSURE 1013.23f
float bmp280_get_altitude(bmp_temperature_data temperature, bmp_pressure_data pressure)
{
/* log_info("temperature:%d,pressure:%d",(s32)temperature,(u32)pressure); */
#if USE_FIXED_POINT_COMPENSATE //使用定点补偿
/* return 44330 * (1.0 - pow(pressure/10000 / SEA_LEVEL_PRESSURE, 0.1903)); */
//计算公式温度用实际值,压强用实际值的百分之一
return ((float)powf(SEA_LEVEL_PRESSURE / ((float)pressure / 10000.0), 0.190223f) - 1.0f) * ((float)temperature / 100.0 + 273.15f) / 0.0065f; // Calculate the altitude in metres
#else //使用浮点补偿
/* return 44330 * (1.0 - pow(pressure/100 / SEA_LEVEL_PRESSURE, 0.1903)); */
//计算公式温度用实际值,压强用实际值的百分之一
return ((float)powf(SEA_LEVEL_PRESSURE / ((float)pressure / 100.0), 0.190223f) - 1.0f) * ((float)temperature + 273.15f) / 0.0065f; // Calculate the altitude in metres
#endif
}
/*************************test*************************/
#if 0
static struct _bmp280_dev_platform_data bmp280_iic_info_test = {
.iic_hdl = 0,
.iic_delay = 0
};
#define _portio 0
void bmp280_init_read_test()
{
u16 i = 0, iii = 40;
bmp_pressure_data bmp_pressure;
bmp_temperature_data bmp_temperature;
float bmp280_altitude = 0;
/* JL_PORTA->DIR &= ~(BIT(0)|BIT(9)|BIT(10)); */
/* JL_PORTA->OUT &= ~(BIT(0)|BIT(9)|BIT(10)); */
iic_init(0);
log_info("bmp280 init***************************\n");
if (bmp280_init(&bmp280_iic_info_test)) {
log_info("bmp280 init ok!***************************\n");
while (iii--) {
bmp280_get_temperature_and_pressure(&bmp_temperature, &bmp_pressure);
/* bmp280_forced_mode_get_temperature_and_pressure(&bmp_temperature , &bmp_pressure); */
bmp280_altitude = bmp280_get_altitude(bmp_temperature, bmp_pressure);
#if USE_FIXED_POINT_COMPENSATE //使用定点补偿
log_info("bmp280 fixed Pressure %ld.%02dpa,temperature:%d.%02dc,alti:%d.%02dm\n", bmp_pressure / 100, bmp_pressure % 100, bmp_temperature / 100, bmp_temperature % 100, (s32)bmp280_altitude, (u32)((s32)(bmp280_altitude * 100) % 100));
#else //使用浮点补偿
log_info("bmp280 float Pressure %d.%02dpa,temperature:%d.%02dc,alti:%d.%02dm\n", (s32)bmp_pressure, (s32)(bmp_pressure * 100) % 100, (s32)bmp_temperature, (s32)(bmp_temperature * 100) % 100, (s32)bmp280_altitude, (u32)((s32)(bmp280_altitude * 100) % 100));
#endif
os_time_dly(50);
}
} else {
log_error("bmp280 init fail!***************************\n");
}
while (1);
}
#endif
#endif