STM32 HAL库驱动BMP390L气压传感器
STM32 HAL库驱动BMP390L气压传感器
参考官方的驱动
https://github.com/boschsensortec/BMP3-Sensor-API
以及芯片的数据手册,使用硬件I2C驱动传感器。
需要用到以下几个文件
bmp3是主要的驱动函数,bmp3_defs是一些宏定义,common中是需要移植的接口函数。
可以参考这个路径下的驱动示例:.\\examples\\read_sensor_data
下面打开的是主函数:
/\\* Copyright (c) 2022 Bosch Sensortec GmbH. All rights reserved. SPDX-License-Identifier: BSD-3-Clause/#include <stdio.h>#include "bmp3.h"
#include "common.h"//
/* Macros /
//
/* Iteration count to run example code */
#define ITERATION UINT8_C(100)//
/* Test code /
//int main(void)
{int8_t rslt;uint8_t loop = 0;uint16_t settings_sel;struct bmp3_dev dev;struct bmp3_data data = { 0 };struct bmp3_settings settings = { 0 };struct bmp3_status status = { { 0 } };/* Interface reference is given as a parameter* For I2C : BMP3_I2C_INTF* For SPI : BMP3_SPI_INTF*/rslt = bmp3_interface_init(&dev, BMP3_I2C_INTF);bmp3_check_rslt("bmp3_interface_init", rslt);rslt = bmp3_init(&dev);bmp3_check_rslt("bmp3_init", rslt);settings.int_settings.drdy_en = BMP3_ENABLE;settings.press_en = BMP3_ENABLE;settings.temp_en = BMP3_ENABLE;settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X;settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X;settings.odr_filter.odr = BMP3_ODR_100_HZ;settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR |BMP3_SEL_DRDY_EN;rslt = bmp3_set_sensor_settings(settings_sel, &settings, &dev);bmp3_check_rslt("bmp3_set_sensor_settings", rslt);settings.op_mode = BMP3_MODE_NORMAL;rslt = bmp3_set_op_mode(&settings, &dev);bmp3_check_rslt("bmp3_set_op_mode", rslt);while (loop < ITERATION){rslt = bmp3_get_status(&status, &dev);bmp3_check_rslt("bmp3_get_status", rslt);/* Read temperature and pressure data iteratively based on data ready interrupt */if ((rslt == BMP3_OK) && (status.intr.drdy == BMP3_ENABLE)){/ First parameter indicates the type of data to be read* BMP3_PRESS_TEMP : To read pressure and temperature data* BMP3_TEMP : To read only temperature data* BMP3_PRESS : To read only pressure data*/rslt = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &dev);bmp3_check_rslt("bmp3_get_sensor_data", rslt);/* NOTE : Read status register again to clear data ready interrupt status */rslt = bmp3_get_status(&status, &dev);bmp3_check_rslt("bmp3_get_status", rslt);#ifdef BMP3_FLOAT_COMPENSATIONprintf("Data[%d] T: %.2f deg C, P: %.2f Pa\\n", loop, (data.temperature), (data.pressure));#elseprintf("Data[%d] T: %ld deg C, P: %lu Pa\\n", loop, (long int)(int32_t)(data.temperature / 100),(long unsigned int)(uint32_t)(data.pressure / 100));#endifloop = loop + 1;}}bmp3_coines_deinit();return rslt;
}
开头局部变量的定义
int8_t rslt;uint8_t loop = 0;uint16_t settings_sel;struct bmp3_dev dev;struct bmp3_data data = { 0 };struct bmp3_settings settings = { 0 };struct bmp3_status status = { { 0 } };
rslt
为配置成功与否的返回值
dev
为设备结构,包含一些驱动的函数指针
/*!* @brief bmp3 device structure*/
struct bmp3_dev
{/*! Chip Id */uint8_t chip_id;/*!* The interface pointer is used to enable the user* to link their interface descriptors for reference during the* implementation of the read and write interfaces to the* hardware.*/void *intf_ptr;/*! Interface Selection* For SPI, interface = BMP3_SPI_INTF* For I2C, interface = BMP3_I2C_INTF/enum bmp3_intf intf;/*! To store interface pointer error */BMP3_INTF_RET_TYPE intf_rslt;/*! Decide SPI or I2C read mechanism */uint8_t dummy_byte;/*! Read function pointer */bmp3_read_fptr_t read;/*! Write function pointer */bmp3_write_fptr_t write;/*! Delay function pointer */bmp3_delay_us_fptr_t delay_us;/*! Trim data */struct bmp3_calib_data calib_data;
};
data
为数据,包含温度数据和压力数据
/*!* @brief bmp3 sensor structure which comprises of temperature and pressure* data.*/
struct bmp3_data
{/*! Compensated temperature */double temperature;/*! Compensated pressure */double pressure;
};
settings
为传感器的相关设置
/*!* @brief bmp3 device settings*/
struct bmp3_settings
{/*! Power mode which user wants to set */uint8_t op_mode;/*! Enable/Disable pressure sensor */uint8_t press_en;/*! Enable/Disable temperature sensor */uint8_t temp_en;/*! ODR and filter configuration */struct bmp3_odr_filter_settings odr_filter;/*! Interrupt configuration */struct bmp3_int_ctrl_settings int_settings;/*! Advance settings */struct bmp3_adv_settings adv_settings;
};
status
为读取的传感器状态
/*!* @brief bmp3 status flags*/
struct bmp3_status
{/*! Interrupt status */struct bmp3_int_status intr;/*! Sensor status */struct bmp3_sens_status sensor;/*! Error status */struct bmp3_err_status err;/*! Power on reset status */uint8_t pwr_on_rst;
};
1.配置底层驱动
主函数的36行rslt = bmp3_interface_init(&dev, BMP3_I2C_INTF);
即为配置底层驱动。
官方的驱动原始代码为:
BMP3_INTF_RET_TYPE bmp3_interface_init(struct bmp3_dev *bmp3, uint8_t intf)
{int8_t rslt = BMP3_OK;struct coines_board_info board_info;if (bmp3 != NULL){int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB, NULL);if (result < COINES_SUCCESS){printf("\\n Unable to connect with Application Board ! \\n" " 1. Check if the board is connected and powered on. \\n" " 2. Check if Application Board USB driver is installed. \\n"" 3. Check if board is in use by another application. (Insufficient permissions to access USB) \\n");exit(result);}result = coines_get_board_info(&board_info);#if defined(PC)setbuf(stdout, NULL);
#endifif (result == COINES_SUCCESS){if ((board_info.shuttle_id != BMP3_SHUTTLE_ID)){printf("! Warning invalid sensor shuttle \\n ," "This application will not support this sensor \\n");}}(void)coines_set_shuttleboard_vdd_vddio_config(0, 0);coines_delay_msec(1000);/* Bus configuration : I2C */if (intf == BMP3_I2C_INTF){printf("I2C Interface\\n");dev_addr = BMP3_ADDR_I2C_PRIM;bmp3->read = bmp3_i2c_read;bmp3->write = bmp3_i2c_write;bmp3->intf = BMP3_I2C_INTF;/* SDO pin is made low */(void)coines_set_pin_config(COINES_SHUTTLE_PIN_SDO, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW);(void)coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_STANDARD_MODE);}/* Bus configuration : SPI */else if (intf == BMP3_SPI_INTF){printf("SPI Interface\\n");dev_addr = COINES_SHUTTLE_PIN_7;bmp3->read = bmp3_spi_read;bmp3->write = bmp3_spi_write;bmp3->intf = BMP3_SPI_INTF;(void)coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_7_5_MHZ, COINES_SPI_MODE0);}coines_delay_msec(1000);(void)coines_set_shuttleboard_vdd_vddio_config(3300, 3300);coines_delay_msec(1000);bmp3->delay_us = bmp3_delay_us;bmp3->intf_ptr = &dev_addr;}else{rslt = BMP3_E_NULL_PTR;}return rslt;
}
因为官方的代码不是通过单片机来用的,因此有很多语句是没用的,单片机驱动需要的只是SPI或者I2C的读写函数以及系统的延时函数。
可以精简为以下的代码
BMP3_INTF_RET_TYPE bmp3_interface_init(struct bmp3_dev *bmp3, uint8_t intf)
{int8_t rslt = BMP3_OK;/* Bus configuration : I2C */if (intf == BMP3_I2C_INTF){printf("I2C Interface\\n");dev_addr = BMP3_ADDR_I2C_SEC;bmp3->read = bmp3_i2c_read;bmp3->write = bmp3_i2c_write;bmp3->intf = BMP3_I2C_INTF;}/* Bus configuration : SPI */else if (intf == BMP3_SPI_INTF){
// printf("SPI Interface\\n");
// // dev_addr = COINES_SHUTTLE_PIN_7;
// bmp3->read = bmp3_spi_read;
// bmp3->write = bmp3_spi_write;
// bmp3->intf = BMP3_SPI_INTF;}HAL_Delay(100);bmp3->delay_us = bmp3_delay_us;bmp3->intf_ptr = &dev_addr;return rslt;
}
这里只用到了I2C,注释掉了SPI相关代码。
dev_addr = BMP3_ADDR_I2C_SEC;
配置的是传感器的I2C地址,这里为0x77
bmp3->read = bmp3_i2c_read;
为配置读I2C函数。
在下面的函数中修改为HAL库的I2C读函数。
/*!* I2C read function map to COINES platform*/
BMP3_INTF_RET_TYPE bmp3_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr)
{uint8_t dev_addr = *(uint8_t *)intf_ptr;return HAL_I2C_Mem_Read(&hi2c1, dev_addr << 0x01, reg_addr, 1, reg_data, (uint16_t)len, 100);
}
bmp3->write = bmp3_i2c_write;
为配置I2C写函数。进行同样的修改。
/*!* I2C write function map to COINES platform*/
BMP3_INTF_RET_TYPE bmp3_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr)
{uint8_t dev_addr = *(uint8_t *)intf_ptr;return HAL_I2C_Mem_Write(&hi2c1, dev_addr << 0x01, reg_addr, 1, (uint8_t *)reg_data, (uint16_t)len, 100);
}
25行bmp3->delay_us = bmp3_delay_us;
为微秒延时的接口,直接只用HAL库延时1ms即可。
/*!* Delay function map to COINES platform*/
void bmp3_delay_us(uint32_t period, void *intf_ptr)
{HAL_Delay(1);
}
2.对传感器进行初始化设置
rslt = bmp3_init(&dev);bmp3_check_rslt("bmp3_init", rslt);settings.int_settings.drdy_en = BMP3_ENABLE;settings.press_en = BMP3_ENABLE;settings.temp_en = BMP3_ENABLE;settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X;settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X;settings.odr_filter.odr = BMP3_ODR_100_HZ;settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR | BMP3_SEL_DRDY_EN;rslt = bmp3_set_sensor_settings(settings_sel, &settings, &dev);bmp3_check_rslt("bmp3_set_sensor_settings", rslt);settings.op_mode = BMP3_MODE_NORMAL;rslt = bmp3_set_op_mode(&settings, &dev);bmp3_check_rslt("bmp3_set_op_mode", rslt);
rslt = bmp3_init(&dev);
是读芯片ID等简单的初始化。
settings.int_settings.drdy_en = BMP3_ENABLE;settings.press_en = BMP3_ENABLE;settings.temp_en = BMP3_ENABLE;settings.odr_filter.press_os = BMP3_OVERSAMPLING_2X;settings.odr_filter.temp_os = BMP3_OVERSAMPLING_2X;settings.odr_filter.odr = BMP3_ODR_100_HZ;settings_sel = BMP3_SEL_PRESS_EN | BMP3_SEL_TEMP_EN | BMP3_SEL_PRESS_OS | BMP3_SEL_TEMP_OS | BMP3_SEL_ODR | BMP3_SEL_DRDY_EN;rslt = bmp3_set_sensor_settings(settings_sel, &settings, &dev);bmp3_check_rslt("bmp3_set_sensor_settings", rslt);
这些是设置芯片的功能,是否开启压力温度检测,过采样设置,输出数据频率设置等。
settings.op_mode = BMP3_MODE_NORMAL;rslt = bmp3_set_op_mode(&settings, &dev);bmp3_check_rslt("bmp3_set_op_mode", rslt);
这里是设置芯片的工作模式,
/\\name Power mode macros */
#define BMP3_MODE_SLEEP UINT8_C(0x00)
#define BMP3_MODE_FORCED UINT8_C(0x01)
#define BMP3_MODE_NORMAL UINT8_C(0x03)
3.读取数据
while (1){rslt = bmp3_get_status(&status, &dev);bmp3_check_rslt("bmp3_get_status", rslt);/* Read temperature and pressure data iteratively based on data ready interrupt */if ((rslt == BMP3_OK) && (status.intr.drdy == BMP3_ENABLE)){/ First parameter indicates the type of data to be read* BMP3_PRESS_TEMP : To read pressure and temperature data* BMP3_TEMP : To read only temperature data* BMP3_PRESS : To read only pressure data*/rslt = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &dev);bmp3_check_rslt("bmp3_get_sensor_data", rslt);/* NOTE : Read status register again to clear data ready interrupt status */rslt = bmp3_get_status(&status, &dev);bmp3_check_rslt("bmp3_get_status", rslt);#ifdef BMP3_FLOAT_COMPENSATIONprintf("{temperature:%.2f}\\r\\n",(data.temperature));printf("{pressure:%.2f}\\r\\n",(data.pressure));
#elseprintf("Data[%d] T: %ld deg C, P: %lu Pa\\n", loop, (long int)(int32_t)(data.temperature / 100),(long unsigned int)(uint32_t)(data.pressure / 100));
#endifloop = loop + 1;}HAL_Delay(10);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}
首先获取传感器状态,之后读取传感器数据,rslt = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &dev);
然后再读一次传感器状态清除掉数据完成的标志位,数据读取结束。
工程文件已经上传。
工程文件下载