四轴无人机BMP280芯片(stm32标准库)二

前篇介绍了寄存器的配置,本篇继续介绍代码的实现,如果有对寄存器不明白的地方可以去看前篇文章https://blog.csdn.net/bunanananaa/article/details/145188798


由于本文主要是记录BMP280传感器的使用,所以对IIC通信就不再赘述.上篇文章讲了BMP280的测量流程为:1.上电检查ID 2.读取补偿寄存器的值 3.复位并配置寄存器 4.检测配置是否成功 5.获取数值 6.数据补偿计算,所以我们先对BMP280初始化,也就是完成前四步.

IIC读取函数

/*****************************************************************************
* 功  能:在从机中读取一个字节数据
* 参  数:I2C_Addr 从机地址
          reg     读取目标寄存器
          *buf    用于保存数据的地址
* 返回值:0成功;1失败
* 备  注:无
*****************************************************************************/
uint8_t IIC_ReadByteFromSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf);


/*****************************************************************************
* 功  能:在从机中连续读取多个字节数据
* 参  数:I2C_Addr 从机地址
          reg     读取目标寄存器
          *buf    用于保存数据的地址
* 返回值:0成功;1失败
* 备  注:无
*****************************************************************************/
uint8_t IIC_ReadMultByteFromSlave(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data);


/*****************************************************************************
* 功  能:向从机写入一个字节数据
* 参  数:I2C_Addr 从机地址
          reg     读取目标寄存器
          buf     写入的数据
* 返回值:0成功;1失败
* 备  注:无
*****************************************************************************/
uint8_t IIC_WriteByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t buf);

这四个函数是我内部已经封装好的读写函数以防后面函数中出现不明白,具体的参数和返回值可以看注释部分标注的很详细.


下面来介绍BMP280初始化这部分代码

寄存器宏定义:

首先是将BMP280的寄存器全部进行宏定义,有利于后面在看代码时能够快速的知道某一步操作的寄存器是干嘛的

//芯片地址
#define bmp280_address      0xEC
//配置寄存器地址
#define bmp280_id           0xD0
#define bmp280_reset 		0xE0
#define bmp280_status       0xF3
#define bmp280_ctrl_meas    0xF4
#define bmp280_config 	    0xF5
//数据寄存器地址
#define bmp280_press_msb    0xF7
#define bmp280_press_lsb    0xF8
#define bmp280_press_xsb    0xF9
#define bmp280_temp_msb     0xFA
#define bmp280_temp_lsb     0xFB
#define bmp280_temp_xsb     0xFC
//校准数据寄存器地址
#define bmp280_dig_t1_lsb   0x88
#define bmp280_dig_t1_msb   0x89
#define bmp280_dig_t2_lsb   0x8A
#define bmp280_dig_t2_msb   0x8B
#define bmp280_dig_t3_lsb   0x8C
#define bmp280_dig_t3_msb   0x8D
#define bmp280_dig_p1_lsb   0x8E
#define bmp280_dig_p1_msb   0x8F
#define bmp280_dig_p2_lsb   0x90
#define bmp280_dig_p2_msb   0x91
#define bmp280_dig_p3_lsb   0x92
#define bmp280_dig_p3_msb   0x93
#define bmp280_dig_p4_lsb   0x94
#define bmp280_dig_p4_msb   0x95
#define bmp280_dig_p5_lsb   0x96
#define bmp280_dig_p5_msb   0x97
#define bmp280_dig_p6_lsb   0x98
#define bmp280_dig_p6_msb   0x99
#define bmp280_dig_p7_lsb   0x9A
#define bmp280_dig_p7_msb   0x9B
#define bmp280_dig_p8_lsb   0x9C
#define bmp280_dig_p8_msb   0x9D
#define bmp280_dig_p9_lsb   0x9E
#define bmp280_dig_p9_msb   0x9F

BMP280初始化:

1.ID读取函数

/*****************************************************************************
* 函  数:uint8_t BMP280_check_id(void)
* 功  能:检测id是否正确
* 参  数:无
* 返回值:0正确; 1失败并打印
* 备  注:无
*****************************************************************************/
uint8_t BMP280_check_id(void)
{
	uint8_t buf;
	IIC_ReadByteFromSlave(bmp280_address,bmp280_id,&buf);//IIC在从机中读取一个字节
	if(buf==0x58)//从机的ID是固定的,检查读出的数据是否匹配
	{
		return 0;
	}
	else
	{
		printf("BMP280 no connected...\r\n");
		return 1;
	}
}

2.获取校准值

首先定义一个结构体来保存我们获取到的校准值(注意结构体内的数据类型),获取结构体之后通过函数将读取到的数值保存到结构体内,代码如下.

//定义一个结构体来保存校准寄存器内的数据,注意t1与p1是无符号16位,其他是有符号16位!!
typedef struct
{
	uint16_t dig_t1;
	int16_t  dig_t2;
	int16_t  dig_t3;
	uint16_t dig_p1;
	int16_t  dig_p2;
	int16_t  dig_p3;
	int16_t  dig_p4;
	int16_t  dig_p5;
	int16_t  dig_p6;
	int16_t  dig_p7;
	int16_t  dig_p8;
	int16_t  dig_p9;
	
} bmp280_Calib;
bmp280_Calib bmp280_cal;//创建结构体
/*****************************************************************************
* 函  数:void BMP280_get_Cal_value(void)
* 功  能:获取校准值
* 参  数:无
* 返回值:无
* 备  注:无
*****************************************************************************/
void BMP280_get_Cal_value(void)
{ 
  uint8_t buf[24];
  IIC_ReadMultByteFromSlave(bmp280_address,bmp280_dig_t1_lsb,24,buf);//IIC读取连续字节的数据
  bmp280_cal.dig_t1=(buf[1]<<8)+buf[0];//将buf中的值传入给结构体,注意MSB在前,LSB在后.
  bmp280_cal.dig_t2=(buf[3]<<8)+buf[2];
  bmp280_cal.dig_t3=(buf[5]<<8)+buf[4];
  bmp280_cal.dig_p1=(buf[7]<<8)+buf[6];
  bmp280_cal.dig_p2=(buf[9]<<8)+buf[8];
  bmp280_cal.dig_p3=(buf[11]<<8)+buf[10];
  bmp280_cal.dig_p4=(buf[13]<<8)+buf[12];
  bmp280_cal.dig_p5=(buf[15]<<8)+buf[14];
  bmp280_cal.dig_p6=(buf[17]<<8)+buf[16];
  bmp280_cal.dig_p7=(buf[19]<<8)+buf[18];
  bmp280_cal.dig_p8=(buf[21]<<8)+buf[20];
  bmp280_cal.dig_p9=(buf[23]<<8)+buf[22];
}

3.复位函数

向复位寄存器写入固定的0xb6来复位

/*****************************************************************************
* 函  数:uint8_t BMP280_reset(void)
* 功  能:BMP280复位
* 参  数:无
* 返回值:0复位成功; 1复位失败打印
* 备  注:无
*****************************************************************************/
uint8_t BMP280_reset(void)
{
	if(IIC_WriteByteToSlave(bmp280_address,bmp280_reset,0XB6)==0)
	{
		return 0;
	}
	else
	{
		printf("BMP280RESET FAIL....\r\n");
		return 1;
	}
}

4.配置寄存器

在配置完寄存器后读取我们所配置的寄存器,查看是否配置成功.

/*****************************************************************************
* 函  数:void BMP280_config(void)
* 功  能:配置BMP280并检测配置是否正确
* 参  数:无
* 返回值:无
* 备  注:在函数内对芯片进行配置如下
*        电源模式:正常模式
*  温度传感器配置:17bit/0.0025℃
*  压力传感器配置:20bit/0.16pa
*    待机时长配置:0.5ms
*      滤波器配置:16
*     SPI是否启用:否(对spi3w_en[0]写0)
*****************************************************************************/
void BMP280_config(void)
{ 
	uint8_t buff_1=0;
	uint8_t buff_2=0;
	IIC_WriteByteToSlave(bmp280_address,bmp280_ctrl_meas,0x57);
	IIC_WriteByteToSlave(bmp280_address,bmp280_config,0x10);
	IIC_ReadByteFromSlave(bmp280_address,bmp280_ctrl_meas,&buff_1);
	IIC_ReadByteFromSlave(bmp280_address,bmp280_config,&buff_2);
	if((buff_1==0x57)&&(buff_2==0x10))
	{
		printf("BMP280CONFIG SUCCESS");
	}
	else
	{
		printf("BMP280CONFIG FAIL....");
	}
}

5.BMP280初始化函数

若初始化失败会提示在哪一步失败并且退出函数不再执行后面的函数,如果初始化成功则会通过串口打印"BMP280CONFIG SUCCESS"字样.

/*****************************************************************************
* 函  数:void BMP280_Init(void)
* 功  能:BMP280初始化
* 参  数:无
* 返回值:无
* 备  注:无
*****************************************************************************/
void BMP280_Init(void)
{
	if(BMP280_check_id()!=0)//检查ID是否正确,若不正确直接退出不继续进行.
	{
		return;
	}
	BMP280_get_Cal_value();//获取校准值
	
	if(BMP280_reset()!=0)//BMP280复位
	{
		return;
	}
	BMP280_config();//对BMP280寄存器进行配置
}


下面来介绍数据计算函数,根据官方提供的函数作为参考实现对温度,压力值的计算.

1.获取芯片内部ADC的值

/*****************************************************************************
* 函  数:void BMP280_get_data(void)
* 功  能:获取芯片内部传感器ADC的值
* 参  数:无
* 返回值:无
* 备  注:都为原始数据不能直接使用
*****************************************************************************/
int32_t bmp280_press_data,bmp280_temp_data,t_fine;//用于保存芯片内读取到的ADC的值
void BMP280_get_data(void)
{
  uint8_t buf[6];
	IIC_ReadMultByteFromSlave(bmp280_address,bmp280_press_msb,6,buf);
	bmp280_press_data=(int32_t)(((buf[0])<<12)|((buf[1])<<4)|((buf[2])>>4));
	bmp280_temp_data=(int32_t)(((buf[3])<<12)|((buf[4])<<4)|((buf[5])>>4));
}

2.温度补偿计算

/*****************************************************************************
* 函  数:int32_t BMP280_compensate_T(int32_t adc_T)
* 功  能:通过补偿计算出温度的值
* 参  数:芯片内部温度传感器的ADC值
* 返回值:温度值*100 (将返回值/100就得到当前温度)
* 备  注:无
*****************************************************************************/
int32_t BMP280_compensate_T(int32_t adc_T)
{
    int32_t var1,var2,T;
    var1=((((adc_T>>3)-((int32_t)bmp280_cal.dig_t1<<1)))*((int32_t)bmp280_cal.dig_t2))>>11;
    var2=(((((adc_T>>4)-((int32_t)bmp280_cal.dig_t1))*((adc_T>>4)-((int32_t)bmp280_cal.dig_t1)))>>12)*((int32_t)bmp280_cal.dig_t3))>>14;
    t_fine=var1+var2; 
    T=(t_fine*5+128)>>8;
    return T;
}

3.大气压补偿计算

/*****************************************************************************
* 函  数:uint32_t BMP280_compensate_P(int32_t adc_P)
* 功  能:通过补偿计算出大气压的值
* 参  数:芯片内部压力传感器的ADC值
* 返回值:大气压值 单位为Pa
* 备  注:无
*****************************************************************************/
uint32_t BMP280_compensate_P(int32_t adc_P)
{
    int64_t var1,var2,p;
    var1=((int64_t)t_fine)-128000;
    var2=var1*var1*(int64_t)bmp280_cal.dig_p6;
    var2=var2+((var1*(int64_t)bmp280_cal.dig_p5)<<17);
    var2=var2+(((int64_t)bmp280_cal.dig_p4)<<35);
    var1=((var1*var1*(int64_t)bmp280_cal.dig_p3)>>8)+((var1*(int64_t)bmp280_cal.dig_p2)<<12);
    var1=(((((int64_t)1)<<47)+var1))*((int64_t)bmp280_cal.dig_p1)>>33;
    if (var1==0)
		{
        return 0;
		}
    p=1048576-adc_P;
    p=(((p<<31)-var2)*3125)/var1;
    var1=(((int64_t)bmp280_cal.dig_p9)*(p>>13)*(p>>13))>>25;
    var2=(((int64_t)bmp280_cal.dig_p8)*p)>>19;
    p=((p+var1+var2)>>8)+(((int64_t)bmp280_cal.dig_p7)<<4);
    return(uint32_t)p/256;
}

最后在主函数内将芯片读取的ADC值传入给这两个补偿函数的参数就可以计算出温度和大气压的值了.

最后附上我这边测得的数据图,还是比较准确的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值