一般来说,使用一个新的芯片,都会去该芯片品牌的官网找相关资料,然后再去网络看是否有人使用过该芯片。bmp280属于博世旗下的一款芯片,该芯片的官方网址在这。
从官网上可以找到对应的datasheet,还有驱动文件,然后两者结合稍微理解一下,然后测试一下基本的数据读写,这个模块就算结束了。总体来说,还是比较简单的。
BMP280是一款气压传感器,体积和功耗都很小,接口方面支持IIC和SPI。引脚定义如下。
依照上图,可知,IIC模式下,3脚为数据脚,4脚为时钟脚,5脚为IIC地址控制脚。2脚在IIC模式下接高电平即可。
在IIC模式下最大速率可到3.4MHz,SPI模式下最大频率10MHz.
- 工作温度范围:-40 - +85 °C
- 测量温度范围:0 - +65°C
- 测量温度误差:25°C ±0.5°C 0…65°C ±1°C
- 测量温度分辨率:0.01°C
- 存储气压范围:0 - 20000 hPa
- 测量气压范围:300 - 1100 hPa
- 测量气压误差:±1 hPa
- 测量气压分辨率:0.16 hPa
剩下的其他参数感兴趣的可以查阅BMP280的datasheet的一二章。
手册里面明确有写,在IIC模式下,地址为111011x,x由 芯片的5脚电平决定。在这里我硬件上接入的是GND,所以地址为0X76.
从上图可知
且温度和压力数据可以通过配置寄存器修改采样精度,滤波也可以通过配置寄存器修改滤波系数。具体的效果都在datasheet里面,官方给出了推荐的配置,如下图所示
比如我使用的场景是低功耗手持设备,按照表格的第一项进行配置即可。
该芯片的寄存器比较少,一共就下图这么多。简单说一下
Register 0XD0 "ID"
芯片ID,固定为0X58,只读。
Register 0XE0 "reset"
写入0XB6可对芯片复位,其他值无效。
Register 0XF3 "status"
bit3:为0时代表数据转换完成。需要极限频率时可根据此位判断数据是否完成转换
bit0:为0时代表补偿的数字被拷贝到寄存器完成。
Register 0xF4 "ctrl_meas"
osrs_t :控制是否跳过温度数据采样
osrs_p:控制是否跳过压力数据采样
mode :电源模式控制
Register 0XF5 "config"
t_sb:控制正常模式下不活动的时间,参考7.1.1
filer :控制滤波器滤波系数
spi3w_en:为1时开启3线SPI模式
Register 0XF7…0XF9 “press”(_msb,_lsb,_xlsb)
在不同采样下,所得数据精度不同,压力的最大精度为0.16Pa,数据长度为20bit,所以需要三个寄存器存放数据.
具体组合方式为(msb << 12) | (lsb << 4) | (xlsb >> 4);
Register 0XFA…0XFc “temp”(_msb,_lsb,_xlsb)
在不同采样下,所得数据精度不同,温度的最大精度为0.0003°C,数据长度为20bit,所以需要三个寄存器存放数据.
具体组合方式为(msb << 12) | (lsb << 4) | (xlsb >> 4);
这一部分其实根据上个小章节的流程图基本就已经确认下来了。这里结合官方给的库总结一下。
到这基本上就结束了了,这里放一下博世官方的驱动,只需要简单补全一下底层收发函数即可.移植流程如下.
1.将驱动文件加入工程.
2. 新建一个C文件,添加五个函数,最后一个函数测试使用.
void delay_ms(uint32_t period_ms)
{
HAL_Delay(period_ms);
}
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
HAL_I2C_Mem_Write(handle, i2c_addr, reg_addr,I2C_MEMADD_SIZE_8BIT, reg_data, len, 1000);
return -1;
}
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
HAL_I2C_Mem_Read(handle, i2c_addr, reg_addr,I2C_MEMADD_SIZE_8BIT, reg_data, len, 1000);
return -1;
}
void bmp280_register(struct bmp280_dev *_dev)
{
_dev->delay_ms = delay_ms;
/* 根据硬件接线进行选择*/
_dev->dev_id = BMP280_I2C_ADDR_PRIM;
//_dev->dev_id = BMP280_I2C_ADDR_SEC;
_dev->intf = BMP280_I2C_INTF; //选择为IIC模式
//_dev->intf = BMP280_SPI_INTF; //SPI模式
_dev->read = i2c_reg_read;
bmp->write = i2c_reg_write;
}
void print_rslt(const char api_name[], int8_t rslt)
{
if (rslt != BMP280_OK)
{
printf("%s\t", api_name);
if (rslt == BMP280_E_NULL_PTR)
{
printf("Error [%d] : Null pointer error\r\n", rslt);
}
else if (rslt == BMP280_E_COMM_FAIL)
{
printf("Error [%d] : Bus communication failed\r\n", rslt);
}
else if (rslt == BMP280_E_IMPLAUS_TEMP)
{
printf("Error [%d] : Invalid Temperature\r\n", rslt);
}
else if (rslt == BMP280_E_DEV_NOT_FOUND)
{
printf("Error [%d] : Device not found\r\n", rslt);
}
else
{
/* For more error codes refer "*_defs.h" */
printf("Error [%d] : Unknown error code\r\n", rslt);
}
}
}
需要注意的是,上面的读写函数内的handle根据自己的硬件配置去更换.
int main()
{
int8_t rslt;
struct bmp280_dev bmp;
struct bmp280_config conf;
struct bmp280_uncomp_data ucomp_data;
uint32_t pres32, pres64;
double pres;
bmp280_register(&bmp);
rslt = bmp280_init(&bmp);
print_rslt(" bmp280_init status", rslt);
rslt = bmp280_get_config(&conf, &bmp);
print_rslt(" bmp280_get_config status", rslt);
/* configuring the temperature oversampling, filter coefficient and output data rate */
/* Overwrite the desired settings */
conf.filter = BMP280_FILTER_COEFF_2;
/* Pressure oversampling set at 4x */
conf.os_pres = BMP280_OS_4X;
/* Setting the output data rate as 1HZ(1000ms) */
conf.odr = BMP280_ODR_1000_MS;
rslt = bmp280_set_config(&conf, &bmp);
print_rslt(" bmp280_set_config status", rslt);
/* Always set the power mode after setting the configuration */
rslt = bmp280_set_power_mode(BMP280_NORMAL_MODE, &bmp);
print_rslt(" bmp280_set_power_mode status", rslt);
while (1)
{
/* Reading the raw data from sensor */
rslt = bmp280_get_uncomp_data(&ucomp_data, &bmp);
/* Getting the compensated pressure using 32 bit precision */
rslt = bmp280_get_comp_pres_32bit(&pres32, ucomp_data.uncomp_press, &bmp);
/* Getting the compensated pressure using 64 bit precision */
rslt = bmp280_get_comp_pres_64bit(&pres64, ucomp_data.uncomp_press, &bmp);
/* Getting the compensated pressure as floating point value */
rslt = bmp280_get_comp_pres_double(&pres, ucomp_data.uncomp_press, &bmp);
printf("UP: %ld, P32: %ld, P64: %ld, P64N: %ld, P: %f\r\n",
ucomp_data.uncomp_press,
pres32,
pres64,
pres64 / 256,
pres);
bmp.delay_ms(1000); /* Sleep time between measurements = BMP280_ODR_1000_MS */
}
return 0;
}
在官方例程里面还有内部温度传感器的使用方法,具体要看temperature.c文件.
因为这个项目涉及到后期的功耗控制,所以这里先把这个芯片的电流消耗等相关参数列出来。
简单理解以1HZ频率进行数据采集时候的电流消耗。如果采样频率为X,则电流消耗为IDD*X
结合下表
两个表综合一起,意思是在1S内,采样一次用时5.5ms,剩下的994.5ms无动作,则消耗2.74ua电流。注意,这个时候传感器还是处于NORMAL模式,并不是sleep mode.