STM32 HAL库驱动BMP390L气压传感器

  • Post author:
  • Post category:其他




STM32 HAL库驱动BMP390L气压传感器

参考官方的驱动

https://github.com/boschsensortec/BMP3-Sensor-API

以及芯片的数据手册,使用硬件I2C驱动传感器。

需要用到以下几个文件


image

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_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;
};



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);
#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);
}



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_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);

然后再读一次传感器状态清除掉数据完成的标志位,数据读取结束。

工程文件已经上传。


工程文件下载



版权声明:本文为Master_0_原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。