BMP280大气压传感器(我直接叫他高度传感器)看似很冷门,或许大家都觉得,大气压不是一个地区就那么一个值.测量它有什么用?但是这个模块很神奇,它测量精度很高,大气压和所处海拔关系密切,但是精度高的特点使得它可以测你的所在高度,你拿着传感器起身,他的ADC值会发生变化.大佬们就用它给飞控定高(也就是很秀的操作,四轴悬浮在那里,一动不动,很神奇吧!),还有可以做天气监控(Weather monitoring,数据手册写的),所以它是很有必要玩玩的。
先说一下别人分享的代码,虽然编程水平很高,但是很难看懂那些结构体,我总结了一些,把我写的分享给大家,比较清楚的代码。我也看了挺久的数据手册,把我的代码和理解分享给大家
先说一下我的风格吧,我不会一次把代码全贴出来,因为你可能会看懵,一步一步来才能深入,不要先做无用功。
BMP280寄存器
#define BMP280_ADDRESS 0x76 //从设备地址
#define BMP280_RESET_VALUE 0xB6 //复位寄存器写入值
#define BMP280_CHIPID_REG 0xD0 /*Chip ID Register */
#define BMP280_RESET_REG 0xE0 /*Softreset Register */
#define BMP280_STATUS_REG 0xF3 /*Status Register */
#define BMP280_CTRLMEAS_REG 0xF4 /*Ctrl Measure Register */
#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */
#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */
#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */
#define BMP280_TEMPERATURE_MSB_REG 0xFA /*Temperature MSB Reg */
#define BMP280_TEMPERATURE_LSB_REG 0xFB /*Temperature LSB Reg */
#define BMP280_TEMPERATURE_XLSB_REG 0xFC /*Temperature XLSB Reg */
//状态寄存器转换标志
#define BMP280_MEASURING 0x01
#define BMP280_IM_UPDATE 0x08
寄存器大概讲一下
1、第一个ID寄存器,读出来好像是0X58,但我的是0X88。
2、第二个复位寄存器,别管太多,让他复位写0xB6就会复位了。
3 、状态寄存器就两个状态,一个是MEASURING,一个是UPDATE,大概意思是当前状态正在测量内部ADC转换,第二个是更新到印象寄存器里。
4、4和5寄存器就是用来设置他的模式了,待会会说
5、最后几个寄存器就是存储ADC读出来的数据寄存器了,XLSB应该是小数位的意思,后面用来浮点转化用的。
I2C基本读写
static uint8_t BMP280_Read_Byte(u8 reg)
{
uint8_t rec_data;
I2C_Start();
I2C_Send_Byte(BMP280_ADDRESS<<1|0);
I2C_Wait_Ack();
I2C_Send_Byte(reg);
I2C_Wait_Ack();
I2C_Start();
I2C_Send_Byte(BMP280_ADDRESS<<1|1);
I2C_Wait_Ack();
rec_data = I2C_Read_Byte(0); //不应答
I2C_Stop();
return rec_data;
}
static void BMP280_Write_Byte(u8 reg,u8 data)
{
I2C_Start();
I2C_Send_Byte(BMP280_ADDRESS<<1);
I2C_Wait_Ack();
I2C_Send_Byte(reg);
I2C_Wait_Ack();
I2C_Send_Byte(data);
I2C_Wait_Ack();
I2C_Stop();
}
我只用到单字节读写,多字节的目前还没用上,一个I2C时序就不发了,网上都有,这很基础的东西
测试你的I2C没出问题,读一下ID试试,我的是0x88,但是后面读出来的大气压和温度都是对的,别担心,这个我也不知道为什么,或许你是对的,只要能读出来就OK
uint8_t BMP280_ReadID(void)
{
return BMP280_Read_Byte(BMP280_CHIPID_REG);
}
相关结构体、枚举的定义
也就几个结构体,比较寄存器才那么两三个东西
/BMP工作模式
typedef enum {
BMP280_SLEEP_MODE = 0x0,
BMP280_FORCED_MODE = 0x1, //可以说0x2
BMP280_NORMAL_MODE = 0x3
} BMP280_WORK_MODE;
//BMP压力过采样因子
typedef enum
{
BMP280_P_MODE_SKIP = 0x0, /*skipped*/
BMP280_P_MODE_1, /*x1*/
BMP280_P_MODE_2, /*x2*/
BMP280_P_MODE_3, /*x4*/
BMP280_P_MODE_4, /*x8*/
BMP280_P_MODE_5 /*x16*/
} BMP280_P_OVERSAMPLING;
//BMP温度过采样因子
typedef enum {
BMP280_T_MODE_SKIP = 0x0, /*skipped*/
BMP280_T_MODE_1, /*x1*/
BMP280_T_MODE_2, /*x2*/
BMP280_T_MODE_3, /*x4*/
BMP280_T_MODE_4, /*x8*/
BMP280_T_MODE_5 /*x16*/
} BMP280_T_OVERSAMPLING;
//IIR滤波器时间常数
typedef enum {
BMP280_FILTER_OFF = 0x0, /*filter off*/
BMP280_FILTER_MODE_1, /*0.223*ODR*/ /*x2*/
BMP280_FILTER_MODE_2, /*0.092*ODR*/ /*x4*/
BMP280_FILTER_MODE_3, /*0.042*ODR*/ /*x8*/
BMP280_FILTER_MODE_4 /*0.021*ODR*/ /*x16*/
} BMP280_FILTER_COEFFICIENT;
//保持时间
typedef enum {
BMP280_T_SB1 = 0x0, /*0.5ms*/
BMP280_T_SB2, /*62.5ms*/
BMP280_T_SB3, /*125ms*/
BMP280_T_SB4, /*250ms*/
BMP280_T_SB5, /*500ms*/
BMP280_T_SB6, /*1000ms*/
BMP280_T_SB7, /*2000ms*/
BMP280_T_SB8, /*4000ms*/
} BMP280_T_SB;
typedef struct
{
/* T1~P9 为补偿系数 */
uint16_t T1;
int16_t T2;
int16_t T3;
uint16_t P1;
int16_t P2;
int16_t P3;
int16_t P4;
int16_t P5;
int16_t P6;
int16_t P7;
int16_t P8;
int16_t P9;
} BMP280;
typedef struct
{
BMP280_P_OVERSAMPLING P_Osample;
BMP280_T_OVERSAMPLING T_Osample;
BMP280_WORK_MODE WORKMODE;
} BMP_OVERSAMPLE_MODE;
typedef struct
{
BMP280_T_SB T_SB;
BMP280_FILTER_COEFFICIENT FILTER_COEFFICIENT;
FunctionalState SPI_EN;
} BMP_CONFIG;
extern BMP280* bmp280;
如果不想看,可以跳过这里,或者待会不懂可以跳回来看一下
1、第一个是模式,三个:睡眠模式、触发模式、正常模式
睡眠模式就是低功耗了,关了不测了;正常模式即连续测,内部一直转化,然后置状态位,我们读寄存器就可以读出原始数据了;触发模式挺有用,你测一次后,传感器进入睡眠模式,下次再测只要重新设置为触发模式就可以再测一次,以此类推,我只说正常模式,触发模式我没写他的代码。你可以自己拓展
2、下面两个都是过采样因子配置,一个是温度,一个是压力,过采样大概是多次采样,获取一个均值,用于滤波
3、这个就是IIR滤波器的常数配置了,可以防止干扰,这些东西也不太需要理解,数据手册中有一个表,针对于不同应用场合,对三个参数进行配置,等会会说一下
4、保持时间,就是两次采样之间的间隔,你在这段时间可以稳定读出寄存器的值
5、下面这个结构体别看很长,就是一个存补偿系数的类型,定义一个全局变量保存,供后面补偿公式计算使用
6、剩余两个结构体就是配置寄存器了,把一个寄存器的东西整合到一起。
PS:BMP280_NORMAL_MODE 这个我看别的文章就直接枚举下去,寄存器是11b才可以进入,所以直接枚举是不行的!我当初在这里浪费了一点时间
BMP280 初始化
要用的矫正数据寄存器,我们不需要了解这些,我是应用的
/*calibration parameters */
#define BMP280_DIG_T1_LSB_REG 0x88
#define BMP280_DIG_T1_MSB_REG 0x89
#define BMP280_DIG_T2_LSB_REG 0x8A
#define BMP280_DIG_T2_MSB_REG 0x8B
#define BMP280_DIG_T3_LSB_REG 0x8C
#define BMP280_DIG_T3_MSB_REG 0x8D
#define BMP280_DIG_P1_LSB_REG 0x8E
#define BMP280_DIG_P1_MSB_REG 0x8F
#define BMP280_DIG_P2_LSB_REG 0x90
#define BMP280_DIG_P2_MSB_REG 0x91
#define BMP280_DIG_P3_LSB_REG 0x92
#define BMP280_DIG_P3_MSB_REG 0x93
#define BMP280_DIG_P4_LSB_REG 0x94
#define BMP280_DIG_P4_MSB_REG 0x95
#define BMP280_DIG_P5_LSB_REG 0x96
#define BMP280_DIG_P5_MSB_REG 0x97
#define BMP280_DIG_P6_LSB_REG 0x98
#define BMP280_DIG_P6_MSB_REG 0x99
#define BMP280_DIG_P7_LSB_REG 0x9A
#define BMP280_DIG_P7_MSB_REG 0x9B
#define BMP280_DIG_P8_LSB_REG 0x9C
#define BMP280_DIG_P8_MSB_REG 0x9D
#define BMP280_DIG_P9_LSB_REG 0x9E
#define BMP280_DIG_P9_MSB_REG 0x9F
自己复制到头文件吧
BMP280* bmp280; //这个全局结构体变量用来保存存在芯片内ROM补偿参数
void Bmp_Init(void)
{
u8 L***,M***;
/********************接下来读出矫正参数*********************/
//温度传感器的矫正值
L*** = BMP280_Read_Byte(BMP280_DIG_T1_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_T1_MSB_REG);
bmp280->T1 = (((u16)M***)<<8) + L***; //高位加低位
L*** = BMP280_Read_Byte(BMP280_DIG_T2_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_T2_MSB_REG);
bmp280->T2 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_T3_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_T3_MSB_REG);
bmp280->T3 = (((u16)M***)<<8) + L***;
//大气压传感器的矫正值
L*** = BMP280_Read_Byte(BMP280_DIG_P1_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P1_MSB_REG);
bmp280->P1 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P2_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P2_MSB_REG);
bmp280->P2 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P3_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P3_MSB_REG);
bmp280->P3 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P4_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P4_MSB_REG);
bmp280->P4 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P5_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P5_MSB_REG);
bmp280->P5 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P6_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P6_MSB_REG);
bmp280->P6 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P7_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P7_MSB_REG);
bmp280->P7 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P8_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P8_MSB_REG);
bmp280->P8 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P9_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P9_MSB_REG);
bmp280->P9 = (((u16)M***)<<8) + L***;
/******************************************************/
BMP280_Write_Byte(BMP280_RESET_REG,BMP280_RESET_VALUE); //往复位寄存器写入给定值
BMP_OVERSAMPLE_MODE BMP_OVERSAMPLE_MODEStructure;
BMP_OVERSAMPLE_MODEStructure.P_Osample = BMP280_P_MODE_3;
BMP_OVERSAMPLE_MODEStructure.T_Osample = BMP280_T_MODE_1;
BMP_OVERSAMPLE_MODEStructure.WORKMODE = BMP280_NORMAL_MODE;
BMP280_Set_TemOversamp(&BMP_OVERSAMPLE_MODEStructure);
BMP_CONFIG BMP_CONFIGStructure;
BMP_CONFIGStructure.T_SB = BMP280_T_SB1;
BMP_CONFIGStructure.FILTER_COEFFICIENT = BMP280_FILTER_MODE_4;
BMP_CONFIGStructure.SPI_EN = DISABLE;
BMP280_Set_Standby_FILTER(&BMP_CONFIGStructure);
}
别看它长啊,前面就是把那些矫正值读出来而已,后面根据官方给的代码移植计算就好了。要先读再复位,因为复位后,他的寄存器读不出来。
//设置BMP过采样因子 MODE
//BMP280_SLEEP_MODE||BMP280_FORCED_MODE||BMP280_NORMAL_MODE
void BMP280_Set_TemOversamp(BMP_OVERSAMPLE_MODE * Oversample_Mode)
{
u8 Regtmp;
Regtmp = ((Oversample_Mode->T_Osample)<<5)|
((Oversample_Mode->P_Osample)<<2)|
((Oversample_Mode)->WORKMODE);
BMP280_Write_Byte(BMP280_CTRLMEAS_REG,Regtmp);
}
//设置保持时间和滤波器分频因子
void 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));
BMP280_Write_Byte(BMP280_CONFIG_REG,Regtmp);
}
然后是开始配置两个寄存器,上面是代码。把数据对齐,写进入。前面说了,两个结构体封装起来了,就跟配置固件库一样用了,先是模式,选正常模式,其他两个先不管,看下面,保持时间选SB1,就是0.5ms,0.5ms够用了。不使能SPI模式。接下来的几个参数,我们根据官方推荐的来配置,人家是开发这个的,跟着来效果肯定最好的。附上图:
按动态手册设备这个来,压力的过采样去X4,就是模式3;温度x1,模式1,滤波器模式4.这就配置好了
获取原始数据
前面是不是有说到一个寄存器,status这个,传过去数据时,可以用来检测状态,确保转换完成
/获取BMP当前状态
//status_flag = BMP280_MEASURING ||
// BMP280_IM_UPDATE
u8 BMP280_GetStatus(u8 status_flag)
{
u8 flag;
flag = BMP280_Read_Byte(BMP280_STATUS_REG);
if(flag&status_flag) return SET;
else return RESET;
}
然后获取原始数据,先别急获取现实值,这个函数后面做一下小修改就得到了
//大气压值-Pa
long BMP280_Get_Pressure(void)
{
uint8_t XL***,L***, M***;
long signed Bit32;
//double pressure;
XL*** = BMP280_Read_Byte(BMP280_PRESSURE_XLSB_REG);
L*** = BMP280_Read_Byte(BMP280_PRESSURE_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_PRESSURE_MSB_REG);
Bit32 = ((long)(M*** << 12))|((long)(L*** << 4))|(XL***>>4); //寄存器的值组合起来
return Bit32 ;
}
main函数是这样的
int main()
{
/*Parameter Configuration*/
long BMP_Pressure;
/*Init*/
delay_init(168);
USART_Config();
MY_I2C_GPIO_Config();
Bmp_Init();
printf("rnBMP280大气压传感器实验");
delay_ms(50);
/*Configuration Operation*/
printf("rnBMP280 ID:0x%d",BMP280_ReadID());
delay_ms(2000); //给你看一下ID
/*LOOP*/
while(1)
{
while(BMP280_GetStatus(BMP280_MEASURING) != RESET);
while(BMP280_GetStatus(BMP280_IM_UPDATE) != RESET);
BMP_Temperature = BMP280_Get_Temperature();
printf("rnPressure %ld",BMP_Pressure);
delay_ms(200);
}
}
获取的数据是变化的,不变基本就是I2C或者前面配置出问题了先回去解决基本问题吧,温度传感器的不发了,等下直接给转换的,两个没啥区别
给大家,估计又加了一波这个模块的销量。。。
BMP280大气压传感器(我直接叫他高度传感器)看似很冷门,或许大家都觉得,大气压不是一个地区就那么一个值.测量它有什么用?但是这个模块很神奇,它测量精度很高,大气压和所处海拔关系密切,但是精度高的特点使得它可以测你的所在高度,你拿着传感器起身,他的ADC值会发生变化.大佬们就用它给飞控定高(也就是很秀的操作,四轴悬浮在那里,一动不动,很神奇吧!),还有可以做天气监控(Weather monitoring,数据手册写的),所以它是很有必要玩玩的。
先说一下别人分享的代码,虽然编程水平很高,但是很难看懂那些结构体,我总结了一些,把我写的分享给大家,比较清楚的代码。我也看了挺久的数据手册,把我的代码和理解分享给大家
先说一下我的风格吧,我不会一次把代码全贴出来,因为你可能会看懵,一步一步来才能深入,不要先做无用功。
BMP280寄存器
#define BMP280_ADDRESS 0x76 //从设备地址
#define BMP280_RESET_VALUE 0xB6 //复位寄存器写入值
#define BMP280_CHIPID_REG 0xD0 /*Chip ID Register */
#define BMP280_RESET_REG 0xE0 /*Softreset Register */
#define BMP280_STATUS_REG 0xF3 /*Status Register */
#define BMP280_CTRLMEAS_REG 0xF4 /*Ctrl Measure Register */
#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */
#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */
#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */
#define BMP280_TEMPERATURE_MSB_REG 0xFA /*Temperature MSB Reg */
#define BMP280_TEMPERATURE_LSB_REG 0xFB /*Temperature LSB Reg */
#define BMP280_TEMPERATURE_XLSB_REG 0xFC /*Temperature XLSB Reg */
//状态寄存器转换标志
#define BMP280_MEASURING 0x01
#define BMP280_IM_UPDATE 0x08
寄存器大概讲一下
1、第一个ID寄存器,读出来好像是0X58,但我的是0X88。
2、第二个复位寄存器,别管太多,让他复位写0xB6就会复位了。
3 、状态寄存器就两个状态,一个是MEASURING,一个是UPDATE,大概意思是当前状态正在测量内部ADC转换,第二个是更新到印象寄存器里。
4、4和5寄存器就是用来设置他的模式了,待会会说
5、最后几个寄存器就是存储ADC读出来的数据寄存器了,XLSB应该是小数位的意思,后面用来浮点转化用的。
I2C基本读写
static uint8_t BMP280_Read_Byte(u8 reg)
{
uint8_t rec_data;
I2C_Start();
I2C_Send_Byte(BMP280_ADDRESS<<1|0);
I2C_Wait_Ack();
I2C_Send_Byte(reg);
I2C_Wait_Ack();
I2C_Start();
I2C_Send_Byte(BMP280_ADDRESS<<1|1);
I2C_Wait_Ack();
rec_data = I2C_Read_Byte(0); //不应答
I2C_Stop();
return rec_data;
}
static void BMP280_Write_Byte(u8 reg,u8 data)
{
I2C_Start();
I2C_Send_Byte(BMP280_ADDRESS<<1);
I2C_Wait_Ack();
I2C_Send_Byte(reg);
I2C_Wait_Ack();
I2C_Send_Byte(data);
I2C_Wait_Ack();
I2C_Stop();
}
我只用到单字节读写,多字节的目前还没用上,一个I2C时序就不发了,网上都有,这很基础的东西
测试你的I2C没出问题,读一下ID试试,我的是0x88,但是后面读出来的大气压和温度都是对的,别担心,这个我也不知道为什么,或许你是对的,只要能读出来就OK
uint8_t BMP280_ReadID(void)
{
return BMP280_Read_Byte(BMP280_CHIPID_REG);
}
相关结构体、枚举的定义
也就几个结构体,比较寄存器才那么两三个东西
/BMP工作模式
typedef enum {
BMP280_SLEEP_MODE = 0x0,
BMP280_FORCED_MODE = 0x1, //可以说0x2
BMP280_NORMAL_MODE = 0x3
} BMP280_WORK_MODE;
//BMP压力过采样因子
typedef enum
{
BMP280_P_MODE_SKIP = 0x0, /*skipped*/
BMP280_P_MODE_1, /*x1*/
BMP280_P_MODE_2, /*x2*/
BMP280_P_MODE_3, /*x4*/
BMP280_P_MODE_4, /*x8*/
BMP280_P_MODE_5 /*x16*/
} BMP280_P_OVERSAMPLING;
//BMP温度过采样因子
typedef enum {
BMP280_T_MODE_SKIP = 0x0, /*skipped*/
BMP280_T_MODE_1, /*x1*/
BMP280_T_MODE_2, /*x2*/
BMP280_T_MODE_3, /*x4*/
BMP280_T_MODE_4, /*x8*/
BMP280_T_MODE_5 /*x16*/
} BMP280_T_OVERSAMPLING;
//IIR滤波器时间常数
typedef enum {
BMP280_FILTER_OFF = 0x0, /*filter off*/
BMP280_FILTER_MODE_1, /*0.223*ODR*/ /*x2*/
BMP280_FILTER_MODE_2, /*0.092*ODR*/ /*x4*/
BMP280_FILTER_MODE_3, /*0.042*ODR*/ /*x8*/
BMP280_FILTER_MODE_4 /*0.021*ODR*/ /*x16*/
} BMP280_FILTER_COEFFICIENT;
//保持时间
typedef enum {
BMP280_T_SB1 = 0x0, /*0.5ms*/
BMP280_T_SB2, /*62.5ms*/
BMP280_T_SB3, /*125ms*/
BMP280_T_SB4, /*250ms*/
BMP280_T_SB5, /*500ms*/
BMP280_T_SB6, /*1000ms*/
BMP280_T_SB7, /*2000ms*/
BMP280_T_SB8, /*4000ms*/
} BMP280_T_SB;
typedef struct
{
/* T1~P9 为补偿系数 */
uint16_t T1;
int16_t T2;
int16_t T3;
uint16_t P1;
int16_t P2;
int16_t P3;
int16_t P4;
int16_t P5;
int16_t P6;
int16_t P7;
int16_t P8;
int16_t P9;
} BMP280;
typedef struct
{
BMP280_P_OVERSAMPLING P_Osample;
BMP280_T_OVERSAMPLING T_Osample;
BMP280_WORK_MODE WORKMODE;
} BMP_OVERSAMPLE_MODE;
typedef struct
{
BMP280_T_SB T_SB;
BMP280_FILTER_COEFFICIENT FILTER_COEFFICIENT;
FunctionalState SPI_EN;
} BMP_CONFIG;
extern BMP280* bmp280;
如果不想看,可以跳过这里,或者待会不懂可以跳回来看一下
1、第一个是模式,三个:睡眠模式、触发模式、正常模式
睡眠模式就是低功耗了,关了不测了;正常模式即连续测,内部一直转化,然后置状态位,我们读寄存器就可以读出原始数据了;触发模式挺有用,你测一次后,传感器进入睡眠模式,下次再测只要重新设置为触发模式就可以再测一次,以此类推,我只说正常模式,触发模式我没写他的代码。你可以自己拓展
2、下面两个都是过采样因子配置,一个是温度,一个是压力,过采样大概是多次采样,获取一个均值,用于滤波
3、这个就是IIR滤波器的常数配置了,可以防止干扰,这些东西也不太需要理解,数据手册中有一个表,针对于不同应用场合,对三个参数进行配置,等会会说一下
4、保持时间,就是两次采样之间的间隔,你在这段时间可以稳定读出寄存器的值
5、下面这个结构体别看很长,就是一个存补偿系数的类型,定义一个全局变量保存,供后面补偿公式计算使用
6、剩余两个结构体就是配置寄存器了,把一个寄存器的东西整合到一起。
PS:BMP280_NORMAL_MODE 这个我看别的文章就直接枚举下去,寄存器是11b才可以进入,所以直接枚举是不行的!我当初在这里浪费了一点时间
BMP280 初始化
要用的矫正数据寄存器,我们不需要了解这些,我是应用的
/*calibration parameters */
#define BMP280_DIG_T1_LSB_REG 0x88
#define BMP280_DIG_T1_MSB_REG 0x89
#define BMP280_DIG_T2_LSB_REG 0x8A
#define BMP280_DIG_T2_MSB_REG 0x8B
#define BMP280_DIG_T3_LSB_REG 0x8C
#define BMP280_DIG_T3_MSB_REG 0x8D
#define BMP280_DIG_P1_LSB_REG 0x8E
#define BMP280_DIG_P1_MSB_REG 0x8F
#define BMP280_DIG_P2_LSB_REG 0x90
#define BMP280_DIG_P2_MSB_REG 0x91
#define BMP280_DIG_P3_LSB_REG 0x92
#define BMP280_DIG_P3_MSB_REG 0x93
#define BMP280_DIG_P4_LSB_REG 0x94
#define BMP280_DIG_P4_MSB_REG 0x95
#define BMP280_DIG_P5_LSB_REG 0x96
#define BMP280_DIG_P5_MSB_REG 0x97
#define BMP280_DIG_P6_LSB_REG 0x98
#define BMP280_DIG_P6_MSB_REG 0x99
#define BMP280_DIG_P7_LSB_REG 0x9A
#define BMP280_DIG_P7_MSB_REG 0x9B
#define BMP280_DIG_P8_LSB_REG 0x9C
#define BMP280_DIG_P8_MSB_REG 0x9D
#define BMP280_DIG_P9_LSB_REG 0x9E
#define BMP280_DIG_P9_MSB_REG 0x9F
自己复制到头文件吧
BMP280* bmp280; //这个全局结构体变量用来保存存在芯片内ROM补偿参数
void Bmp_Init(void)
{
u8 L***,M***;
/********************接下来读出矫正参数*********************/
//温度传感器的矫正值
L*** = BMP280_Read_Byte(BMP280_DIG_T1_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_T1_MSB_REG);
bmp280->T1 = (((u16)M***)<<8) + L***; //高位加低位
L*** = BMP280_Read_Byte(BMP280_DIG_T2_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_T2_MSB_REG);
bmp280->T2 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_T3_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_T3_MSB_REG);
bmp280->T3 = (((u16)M***)<<8) + L***;
//大气压传感器的矫正值
L*** = BMP280_Read_Byte(BMP280_DIG_P1_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P1_MSB_REG);
bmp280->P1 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P2_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P2_MSB_REG);
bmp280->P2 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P3_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P3_MSB_REG);
bmp280->P3 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P4_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P4_MSB_REG);
bmp280->P4 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P5_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P5_MSB_REG);
bmp280->P5 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P6_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P6_MSB_REG);
bmp280->P6 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P7_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P7_MSB_REG);
bmp280->P7 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P8_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P8_MSB_REG);
bmp280->P8 = (((u16)M***)<<8) + L***;
L*** = BMP280_Read_Byte(BMP280_DIG_P9_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_DIG_P9_MSB_REG);
bmp280->P9 = (((u16)M***)<<8) + L***;
/******************************************************/
BMP280_Write_Byte(BMP280_RESET_REG,BMP280_RESET_VALUE); //往复位寄存器写入给定值
BMP_OVERSAMPLE_MODE BMP_OVERSAMPLE_MODEStructure;
BMP_OVERSAMPLE_MODEStructure.P_Osample = BMP280_P_MODE_3;
BMP_OVERSAMPLE_MODEStructure.T_Osample = BMP280_T_MODE_1;
BMP_OVERSAMPLE_MODEStructure.WORKMODE = BMP280_NORMAL_MODE;
BMP280_Set_TemOversamp(&BMP_OVERSAMPLE_MODEStructure);
BMP_CONFIG BMP_CONFIGStructure;
BMP_CONFIGStructure.T_SB = BMP280_T_SB1;
BMP_CONFIGStructure.FILTER_COEFFICIENT = BMP280_FILTER_MODE_4;
BMP_CONFIGStructure.SPI_EN = DISABLE;
BMP280_Set_Standby_FILTER(&BMP_CONFIGStructure);
}
别看它长啊,前面就是把那些矫正值读出来而已,后面根据官方给的代码移植计算就好了。要先读再复位,因为复位后,他的寄存器读不出来。
//设置BMP过采样因子 MODE
//BMP280_SLEEP_MODE||BMP280_FORCED_MODE||BMP280_NORMAL_MODE
void BMP280_Set_TemOversamp(BMP_OVERSAMPLE_MODE * Oversample_Mode)
{
u8 Regtmp;
Regtmp = ((Oversample_Mode->T_Osample)<<5)|
((Oversample_Mode->P_Osample)<<2)|
((Oversample_Mode)->WORKMODE);
BMP280_Write_Byte(BMP280_CTRLMEAS_REG,Regtmp);
}
//设置保持时间和滤波器分频因子
void 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));
BMP280_Write_Byte(BMP280_CONFIG_REG,Regtmp);
}
然后是开始配置两个寄存器,上面是代码。把数据对齐,写进入。前面说了,两个结构体封装起来了,就跟配置固件库一样用了,先是模式,选正常模式,其他两个先不管,看下面,保持时间选SB1,就是0.5ms,0.5ms够用了。不使能SPI模式。接下来的几个参数,我们根据官方推荐的来配置,人家是开发这个的,跟着来效果肯定最好的。附上图:
按动态手册设备这个来,压力的过采样去X4,就是模式3;温度x1,模式1,滤波器模式4.这就配置好了
获取原始数据
前面是不是有说到一个寄存器,status这个,传过去数据时,可以用来检测状态,确保转换完成
/获取BMP当前状态
//status_flag = BMP280_MEASURING ||
// BMP280_IM_UPDATE
u8 BMP280_GetStatus(u8 status_flag)
{
u8 flag;
flag = BMP280_Read_Byte(BMP280_STATUS_REG);
if(flag&status_flag) return SET;
else return RESET;
}
然后获取原始数据,先别急获取现实值,这个函数后面做一下小修改就得到了
//大气压值-Pa
long BMP280_Get_Pressure(void)
{
uint8_t XL***,L***, M***;
long signed Bit32;
//double pressure;
XL*** = BMP280_Read_Byte(BMP280_PRESSURE_XLSB_REG);
L*** = BMP280_Read_Byte(BMP280_PRESSURE_LSB_REG);
M*** = BMP280_Read_Byte(BMP280_PRESSURE_MSB_REG);
Bit32 = ((long)(M*** << 12))|((long)(L*** << 4))|(XL***>>4); //寄存器的值组合起来
return Bit32 ;
}
main函数是这样的
int main()
{
/*Parameter Configuration*/
long BMP_Pressure;
/*Init*/
delay_init(168);
USART_Config();
MY_I2C_GPIO_Config();
Bmp_Init();
printf("rnBMP280大气压传感器实验");
delay_ms(50);
/*Configuration Operation*/
printf("rnBMP280 ID:0x%d",BMP280_ReadID());
delay_ms(2000); //给你看一下ID
/*LOOP*/
while(1)
{
while(BMP280_GetStatus(BMP280_MEASURING) != RESET);
while(BMP280_GetStatus(BMP280_IM_UPDATE) != RESET);
BMP_Temperature = BMP280_Get_Temperature();
printf("rnPressure %ld",BMP_Pressure);
delay_ms(200);
}
}
获取的数据是变化的,不变基本就是I2C或者前面配置出问题了先回去解决基本问题吧,温度传感器的不发了,等下直接给转换的,两个没啥区别
给大家,估计又加了一波这个模块的销量。。。
举报