参考官方的驱动
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
#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_COMPENSATION
printf("Data[%d] T: %.2f deg C, P: %.2f Pa\n", loop, (data.temperature), (data.pressure));
#else
printf("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));
#endif
loop = 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;
};
主函数的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);
#endif
if (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);
}
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)
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_COMPENSATION
printf("{temperature:%.2f}\r\n",(data.temperature));
printf("{pressure:%.2f}\r\n",(data.pressure));
#else
printf("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));
#endif
loop = loop + 1;
}
HAL_Delay(10);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
首先获取传感器状态,之后读取传感器数据,rslt = bmp3_get_sensor_data(BMP3_PRESS_TEMP, &data, &dev);
然后再读一次传感器状态清除掉数据完成的标志位,数据读取结束。
工程文件已经上传。
工程文件下载