STM32 I2C Library for BMP581 Pressure Sensor

STM32 I2C Library for BMP581 Pressure Sensor

Please read Liability Disclaimer and License Agreement CAREFULLY

Before going further please read BMP581 datasheet

In BMP581.h add the following code

#ifndef __BMP581_H
#define __BMP581_H

#ifdef __cplusplus
extern "C" {
#endif

#include "i2c.h"

#define ONE						1
#define TWO						2
#define SIX						6
#define TEMP_COEFF		65536.0f
#define PRESS_COEFF		6400.0f

// BMP581 I2C address
#define BMP581_ADDRESS  0x8C  // 0x46 << 1

// Chip id of BMP581
#define BMP581_CHIP_ID_PRIM    0x50
#define BMP581_CHIP_ID_SEC     0x51

// Register addresses
#define BMP581_REG_CHIP_ID      0x01
#define BMP581_REG_REV_ID       0x02
#define BMP581_REG_CHIP_STATUS  0x11
#define BMP581_REG_DRIVE_CONFIG 0x13
#define BMP581_REG_INT_CONFIG   0x14
#define BMP581_REG_INT_SOURCE   0x15
#define BMP581_REG_FIFO_CONFIG  0x16
#define BMP581_REG_FIFO_COUNT   0x17
#define BMP581_REG_FIFO_SEL     0x18
#define BMP581_REG_TEMP_DATA_XLSB  0x1D
#define BMP581_REG_TEMP_DATA_LSB   0x1E
#define BMP581_REG_TEMP_DATA_MSB   0x1F
#define BMP581_REG_PRESS_DATA_XLSB 0x20
#define BMP581_REG_PRESS_DATA_LSB  0x21
#define BMP581_REG_PRESS_DATA_MSB  0x22
#define BMP581_REG_INT_STATUS    0x27
#define BMP581_REG_STATUS        0x28
#define BMP581_REG_FIFO_DATA     0x29
#define BMP581_REG_NVM_ADDR      0x2B
#define BMP581_REG_NVM_DATA_LSB  0x2C
#define BMP581_REG_NVM_DATA_MSB  0x2D
#define BMP581_REG_DSP_CONFIG    0x30
#define BMP581_REG_DSP_IIR       0x31
#define BMP581_REG_OOR_THR_P_LSB 0x32
#define BMP581_REG_OOR_THR_P_MSB 0x33
#define BMP581_REG_OOR_RANGE     0x34
#define BMP581_REG_OOR_CONFIG    0x35
#define BMP581_REG_OSR_CONFIG    0x36
#define BMP581_REG_ODR_CONFIG    0x37
#define BMP581_REG_OSR_EFF       0x38
#define BMP581_REG_CMD           0x7E

typedef enum {
    BMP581_HIF_MODE_I2C_ONLY            = 0x0,  // 0b00: I2C Mode Only (SPI disabled)
    BMP581_HIF_MODE_SPI_MODE1_MODE2     = 0x1,  // 0b01: SPI Mode1 and Mode2
    BMP581_HIF_MODE_SPI_MODE0_MODE3     = 0x2,  // 0b10: SPI Mode0 and Mode3
    BMP581_HIF_MODE_SPI_I2C_AUTOCONFIG  = 0x3   // 0b11: SPI and I2C available (autoconfig)
} BMP581_hif_mode_t;

typedef enum {
    BMP581_I3C_ERR_0_NO_ERROR    = 0x0,  // 0b0: No SDR parity error occurred
    BMP581_I3C_ERR_0_ERROR       = 0x1   // 0b1: SDR parity error occurred
} BMP581_i3c_err_0_t;

typedef enum {
    BMP581_I3C_ERR_3_NO_ERROR    = 0x0,  // 0b0: No S0/S1 error occurred
    BMP581_I3C_ERR_3_ERROR       = 0x1   // 0b1: S0/S1 error occurred
} BMP581_i3c_err_3_t;

typedef enum {
    BMP581_I2C_CSB_PULLUP_DISABLED = 0x0,  // 0b0: Pullup disabled
    BMP581_I2C_CSB_PULLUP_ENABLED  = 0x1   // 0b1: Pullup enabled
} BMP581_i2c_csb_pup_en_t;

typedef enum {
    BMP581_SPI_4WIRE_MODE = 0x0,  // 0b0: SPI 4-wire mode
    BMP581_SPI_3WIRE_MODE = 0x1   // 0b1: SPI 3-wire mode
} BMP581_spi3_en_t;

typedef enum {
    BMP581_PAD_DRV_LOW  = 0x0,  // 0b0: Low drive strength
    BMP581_PAD_DRV_HIGH = 0x1   // 0b1: High drive strength
} BMP581_pad_if_drv_t;

typedef enum {
    BMP581_INT_MODE_PULSED  = 0x0,  // 0b0: Pulsed
    BMP581_INT_MODE_LATCHED = 0x1   // 0b1: Latched
} BMP581_int_mode_t;

typedef enum {
    BMP581_INT_POL_ACTIVE_LOW  = 0x0,  // 0b0: Active Low
    BMP581_INT_POL_ACTIVE_HIGH = 0x1   // 0b1: Active High
} BMP581_int_pol_t;

typedef enum {
    BMP581_INT_PIN_PUSH_PULL  = 0x0,  // 0b0: Push-Pull
    BMP581_INT_PIN_OPEN_DRAIN = 0x1   // 0b1: Open-Drain
} BMP581_int_od_t;

typedef enum {
    BMP581_INT_DISABLE = 0x0,  // 0b0: Interrupts disabled
    BMP581_INT_ENABLE  = 0x1   // 0b1: Interrupts enabled
} BMP581_int_en_t;

typedef enum {
    BMP581_INT_DRV_LOW  = 0x0,  // 0b0: Low drive strength
    BMP581_INT_DRV_HIGH = 0x1   // 0b1: High drive strength
} BMP581_pad_int_drv_t;

typedef enum {
    BMP581_DRDY_DISABLE = 0x0,  // 0b0: Data Ready interrupt disabled
    BMP581_DRDY_ENABLE  = 0x1   // 0b1: Data Ready interrupt enabled
} BMP581_drdy_data_reg_en_t;

typedef enum {
    BMP581_FIFO_FULL_DISABLE = 0x0,  // 0b0: FIFO Full interrupt disabled
    BMP581_FIFO_FULL_ENABLE  = 0x1   // 0b1: FIFO Full interrupt enabled
} BMP581_fifo_full_en_t;

typedef enum {
    BMP581_FIFO_THS_DISABLE = 0x0,  // 0b0: FIFO Threshold/Watermark interrupt disabled
    BMP581_FIFO_THS_ENABLE  = 0x1   // 0b1: FIFO Threshold/Watermark interrupt enabled
} BMP581_fifo_ths_en_t;

typedef enum {
    BMP581_OOR_P_DISABLE = 0x0,  // 0b0: Pressure Out-of-Range interrupt disabled
    BMP581_OOR_P_ENABLE  = 0x1   // 0b1: Pressure Out-of-Range interrupt enabled
} BMP581_oor_p_en_t;

typedef enum {
    BMP581_FIFO_THR_DISABLE = 0x00,  // 0x0: Disable the FIFO threshold
    BMP581_FIFO_THR_31_FRAMES = 0x1F // 0x1F: Set the FIFO threshold to 31 frames
} BMP581_fifo_threshold_t;

typedef enum {
    BMP581_FIFO_MODE_STREAM = 0x0,  // 0b0: Stream-to-FIFO Mode
    BMP581_FIFO_MODE_STOP_ON_FULL = 0x1  // 0b1: STOP-on-FULL Mode
} BMP581_fifo_mode_t;

typedef enum {
    BMP581_FIFO_NOT_ENABLED = 0x0,         // 0b00: FIFO not enabled
    BMP581_FIFO_TEMP_DATA = 0x1,           // 0b01: Temperature data
    BMP581_FIFO_PRESSURE_DATA = 0x2,       // 0b10: Pressure data
    BMP581_FIFO_PRESS_TEMP_DATA = 0x3      // 0b11: Pressure and temperature data
} BMP581_fifo_frame_s_t;

typedef enum {
    BMP581_FIFO_NO_DOWNSAMPLING = 0x0,     // 0b000: No decimation
    BMP581_FIFO_DOWNSAMPLING_2X = 0x1,     // 0b001: 2x downsampling
    BMP581_FIFO_DOWNSAMPLING_4X = 0x2,     // 0b010: 4x downsampling
    BMP581_FIFO_DOWNSAMPLING_8X = 0x3,     // 0b011: 8x downsampling
    BMP581_FIFO_DOWNSAMPLING_16X = 0x4,    // 0b100: 16x downsampling
    BMP581_FIFO_DOWNSAMPLING_32X = 0x5,    // 0b101: 32x downsampling
    BMP581_FIFO_DOWNSAMPLING_64X = 0x6,    // 0b110: 64x downsampling
    BMP581_FIFO_DOWNSAMPLING_128X = 0x7    // 0b111: 128x downsampling
} BMP581_fifo_dec_sel_t;

typedef enum {
    BMP581_COMP_NONE            = 0x0,  // 0b00: No compensation for both Pressure and Temperature
    BMP581_COMP_TEMP_ONLY       = 0x1,  // 0b01: No Pressure compensation, Temperature compensation enabled
    BMP581_COMP_PRESS_TEMP      = 0x2,  // 0b10: Compensation enabled for both Pressure and Temperature
    BMP581_COMP_PRESS_TEMP_BOTH = 0x3   // 0b11: Compensation enabled for both Pressure and Temperature
} BMP581_comp_pt_en_t;

typedef enum {
    BMP581_IIR_FLUSH_DISABLED = 0x0,  // 0b0: IIR flush disabled
    BMP581_IIR_FLUSH_ENABLED  = 0x1   // 0b1: IIR flush enabled in FORCED mode
} BMP581_iir_flush_forced_en_t;

typedef enum {
    BMP581_IIR_BEFORE_FILTER = 0x0,  // 0b0: Value selected before IIR filter
    BMP581_IIR_AFTER_FILTER  = 0x1   // 0b1: Value selected after IIR filter
} BMP581_iir_selection_t;

typedef enum {
    BMP581_OOR_IIR_BEFORE_FILTER = 0x0,  // 0b0: Value selected before IIR filter
    BMP581_OOR_IIR_AFTER_FILTER  = 0x1   // 0b1: Value selected after IIR filter
} BMP581_oor_iir_sel_t;

typedef enum {
    BMP581_IIR_BYPASS    = 0x0,  // 0b000: Bypass
    BMP581_IIR_COEFF_1   = 0x1,  // 0b001: Filter Coefficient: 1
    BMP581_IIR_COEFF_3   = 0x2,  // 0b010: Filter Coefficient: 3
    BMP581_IIR_COEFF_7   = 0x3,  // 0b011: Filter Coefficient: 7
    BMP581_IIR_COEFF_15  = 0x4,  // 0b100: Filter Coefficient: 15
    BMP581_IIR_COEFF_31  = 0x5,  // 0b101: Filter Coefficient: 31
    BMP581_IIR_COEFF_63  = 0x6,  // 0b110: Filter Coefficient: 63
    BMP581_IIR_COEFF_127 = 0x7   // 0b111: Filter Coefficient: 127
} BMP581_iir_filter_coeff_t;

typedef enum {
    BMP581_OOR_CNT_LIMIT_1  = 0x0,  // Counter limit of 1
    BMP581_OOR_CNT_LIMIT_3  = 0x1,  // Counter limit of 3
    BMP581_OOR_CNT_LIMIT_7  = 0x2,  // Counter limit of 7
    BMP581_OOR_CNT_LIMIT_15 = 0x3   // Counter limit of 15
} BMP581_oor_cnt_limit_t;

typedef enum {
    BMP581_OSR_1X    = 0x0,  // Oversampling rate = 1x
    BMP581_OSR_2X    = 0x1,  // Oversampling rate = 2x
    BMP581_OSR_4X    = 0x2,  // Oversampling rate = 4x
    BMP581_OSR_8X    = 0x3,  // Oversampling rate = 8x
    BMP581_OSR_16X   = 0x4,  // Oversampling rate = 16x
    BMP581_OSR_32X   = 0x5,  // Oversampling rate = 32x
    BMP581_OSR_64X   = 0x6,  // Oversampling rate = 64x
    BMP581_OSR_128X  = 0x7   // Oversampling rate = 128x
} BMP581_osr_t;

typedef enum {
    BMP581_PWRMODE_STANDBY  = 0x0,  // Standby mode: no measurement ongoing
    BMP581_PWRMODE_NORMAL   = 0x1,  // Normal mode: measurement in configured ODR grid
    BMP581_PWRMODE_FORCED   = 0x2,  // Forced mode: forced one-time measurement
    BMP581_PWRMODE_NONSTOP  = 0x3   // Non-Stop mode: repetitive measurements without further duty-cycling
} BMP581_pwr_mode_t;

typedef enum {
    BMP581_ODR_240_HZ   = 0x0,  // 240.000 Hz
    BMP581_ODR_218_HZ   = 0x1,  // 218.537 Hz
    BMP581_ODR_199_HZ   = 0x2,  // 199.111 Hz
    BMP581_ODR_179_HZ   = 0x3,  // 179.200 Hz
    BMP581_ODR_160_HZ   = 0x4,  // 160.000 Hz
    BMP581_ODR_149_HZ   = 0x5,  // 149.333 Hz
    BMP581_ODR_140_HZ   = 0x6,  // 140.000 Hz
    BMP581_ODR_129_HZ   = 0x7,  // 129.855 Hz
    BMP581_ODR_120_HZ   = 0x8,  // 120.000 Hz
    BMP581_ODR_110_HZ   = 0x9,  // 110.164 Hz
    BMP581_ODR_100_HZ   = 0xA,  // 100.299 Hz
    BMP581_ODR_89_HZ    = 0xB,  // 89.600 Hz
    BMP581_ODR_80_HZ    = 0xC,  // 80.000 Hz
    BMP581_ODR_70_HZ    = 0xD,  // 70.000 Hz
    BMP581_ODR_60_HZ    = 0xE,  // 60.000 Hz
    BMP581_ODR_50_HZ    = 0xF,  // 50.056 Hz
    BMP581_ODR_45_HZ    = 0x10, // 45.025 Hz
    BMP581_ODR_40_HZ    = 0x11, // 40.000 Hz
    BMP581_ODR_35_HZ    = 0x12, // 35.000 Hz
    BMP581_ODR_30_HZ    = 0x13, // 30.000 Hz
    BMP581_ODR_25_HZ    = 0x14, // 25.005 Hz
    BMP581_ODR_20_HZ    = 0x15, // 20.000 Hz
    BMP581_ODR_15_HZ    = 0x16, // 15.000 Hz
    BMP581_ODR_10_HZ    = 0x17, // 10.000 Hz
    BMP581_ODR_5_HZ     = 0x18, // 5.000 Hz
    BMP581_ODR_4_HZ     = 0x19, // 4.000 Hz
    BMP581_ODR_3_HZ     = 0x1A, // 3.000 Hz
    BMP581_ODR_2_HZ     = 0x1B, // 2.000 Hz
    BMP581_ODR_1_HZ     = 0x1C, // 1.000 Hz
    BMP581_ODR_0_5_HZ   = 0x1D, // 0.500 Hz
    BMP581_ODR_0_25_HZ  = 0x1E, // 0.250 Hz
    BMP581_ODR_0_125_HZ = 0x1F  // 0.125 Hz
} BMP581_odr_sel_t;

typedef enum {
    BMP581_DEEP_ENABLED  = 0,  // Enable deep standby mode
    BMP581_DEEP_DISABLED = 1   // Disable deep standby mode
} BMP581_deep_standby_t;

typedef enum {
    BMP581_CMD_NO_CMD        = 0x00, // Reserved. No command.
    BMP581_CMD_NVM_WRITE_1   = 0x5D, // First CMD in the sequence 0x5D, 0xA0/0xA5 for NVM write/read.
    BMP581_CMD_EXT_MODE_1    = 0x69, // Last CMD in the sequence for enabling extended mode.
    BMP581_CMD_EXT_MODE_2    = 0x73, // Part of sequence for enabling extended mode.
    BMP581_CMD_NVM_WRITE_2   = 0xA0, // Last CMD in the sequence 0x5D, 0xA0 for NVM write.
    BMP581_CMD_NVM_READ      = 0xA5, // Last CMD in the sequence 0x5D, 0xA5 for NVM read.
    BMP581_CMD_EXT_MODE_3    = 0xB4, // Part of sequence for enabling extended mode.
    BMP581_CMD_RESET         = 0xB6  // Triggers a reset, resetting all user settings to default.
} BMP581_cmd_t;


// ASIC Status Register (0x11)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t hif_mode   : 2;  // Bits 0-1: HIF mode (NVM-backed)
            uint8_t i3c_err_0  : 1;  // Bit 2: SDR parity error occurred
            uint8_t i3c_err_3  : 1;  // Bit 3: S0/S1 error occurred
            uint8_t reserved   : 4; // Bits 4-7: Reserved
        } BitField;
    } Val;
} BMP581_asic_status_t;

// Host Interface Related Settings (0x13)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t i2c_csb_pup_en  : 1;  // Bit 0: CSB pullup selection (valid in I2C mode only)
            uint8_t spi3_en         : 1;  // Bit 1: SPI 3-wire mode enabling
            uint8_t reserved_1      : 2;  // Bit 2-3: Reserved
            uint8_t pad_if_drv      : 1;  // Bit 4: Pad drive strength for serial IO pins (valid in I2C mode only)
            uint8_t reserved_2    	: 3;  // Bits 5-7: Reserved
        } BitField;
    } Val;
} BMP581_host_if_config_t;

// Interrupt Configuration Register (0x14)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t int_mode      : 1;  // Bit 0: INT mode (pulsed or latched)
            uint8_t int_pol       : 1;  // Bit 1: INT polarity (active low or active high)
            uint8_t int_od        : 1;  // Bit 2: INT pin (push-pull or open drain)
            uint8_t int_en        : 1;  // Bit 3: Interrupt enabling
            uint8_t pad_int_drv   : 1;  // Bit 4: Pad drive strength for INT
            uint8_t reserved      : 3;  // Bits 5-7: Reserved
        } BitField;
    } Val;
} BMP581_int_config_t;

// INT Source Selection Register (0x15)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t drdy_data_reg_en : 1;  // Bit 0: Data Ready interrupt enable
            uint8_t fifo_full_en      : 1;  // Bit 1: FIFO Full interrupt enable
            uint8_t fifo_ths_en       : 1;  // Bit 2: FIFO Threshold/Watermark interrupt enable
            uint8_t oor_p_en          : 1;  // Bit 3: Pressure Out-of-Range interrupt enable
            uint8_t reserved		      : 4;  // Bits 4-7: Reserved
        } BitField;
    } Val;
} BMP581_int_source_t;

// FIFO Configuration Register (0x16)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t fifo_threshold : 5;  // Bits 0-4: FIFO threshold value
            uint8_t fifo_mode      : 1;  // Bit 5: FIFO mode control
            uint8_t reserved		   : 2;  // Bits 6-7: Reserved
        } BitField;
    } Val;
} BMP581_fifo_config_t;

// Number of Frames in FIFO Register (0x17)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t fifo_count   : 6;  // Bits 0-5: Number of frames in FIFO
            uint8_t reserved		 : 2;  // Bits 6-7: Reserved
        } BitField;
    } Val;
} BMP581_fifo_count_t;

// FIFO Selection Configuration Register (0x18)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t fifo_frame_sel : 2;  // Bits 0-1: FIFO frame data source selection
            uint8_t fifo_dec_sel   : 3;  // Bits 2-4: FIFO decimation selection
            uint8_t reserved		   : 3;  // Bits 5-7: Reserved
        } BitField;
    } Val;
} BMP581_fifo_frame_sel_t;

// BMP5 sensor data structure for temperature and pressure (0x1D - 0x1F) + (0x20 - 0x22)
typedef struct __attribute__((packed)) {
    float pressure;    // Pressure data in Pa
    float temperature; // Temperature data in degrees Celsius
} BMP581_sensor_data_t;

// Interrupt Status Register (0x27)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t drdy_data_reg  : 1;  // Bit 0: Data Ready
            uint8_t fifo_full      : 1;  // Bit 1: FIFO Full
            uint8_t fifo_ths       : 1;  // Bit 2: FIFO Threshold/Watermark
            uint8_t oor_p          : 1;  // Bit 3: Pressure data out-of-range
            uint8_t por            : 1;  // Bit 4: POR or software reset complete
            uint8_t reserved   		 : 3;  // Bits 5-7: Reserved
        } BitField;
    } Val;
} BMP581_int_status_t;

// Status Register (0x28)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t status_core_rdy      	    : 1;  // Bit 0: Digital core domain is accessible
            uint8_t status_nvm_rdy       	    : 1;  // Bit 1: Device is ready for NVM operations
            uint8_t status_nvm_err       		  : 1;  // Bit 2: Indicates an NVM error
            uint8_t status_nvm_cmd_err    	  : 1;  // Bit 3: Indicates a boot command error
            uint8_t status_boot_err_corrected : 1;  // Bit 4: Indicates that an error was corrected by ECC
            uint8_t reserved			            : 2;  // Bits 5-6: Reserved
            uint8_t st_crack_pass           	: 1;  // Bit 7: Crack check successfully executed
        } BitField;
    } Val;
} BMP581_status_t;

// NVM Address Register (0x2B)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t nvm_row_address  : 6;  // Bits 0-5: NVM row address
            uint8_t nvm_prog_en      : 1;  // Bit 6: NVM programming enable
            uint8_t reserved         : 1;  // Bit 7: Reserved
        } BitField;
    } Val;
} BMP581_nvm_addr_t;

// DSP Configuration Register (0x30)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            BMP581_comp_pt_en_t           comp_pt_en           : 2;  // Bits 0-1: Pressure/Temperature sensor compensation enable
            BMP581_iir_flush_forced_en_t  iir_flush_forced_en  : 1;  // Bit 2: IIR flush for FORCED mode
            BMP581_iir_selection_t        shdw_sel_iir_t       : 1;  // Bit 3: Temperature Data Registers IIR selection
            BMP581_iir_selection_t        fifo_sel_iir_t       : 1;  // Bit 4: FIFO IIR selection for temperature data
            BMP581_iir_selection_t        shdw_sel_iir_p       : 1;  // Bit 5: Shadow Registers IIR selection for pressure data
            BMP581_iir_selection_t        fifo_sel_iir_p       : 1;  // Bit 6: FIFO IIR selection for pressure data
            BMP581_oor_iir_sel_t          oor_sel_iir_p        : 1;  // Bit 7: OOR IIR selection for pressure data
        } BitField;
    } Val;
} BMP581_dsp_config_t;

// DSP IIR Configuration (0x31)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            BMP581_iir_filter_coeff_t set_iir_p : 3;  // Bits 0-2: Pressure IIR LPF band filter selection
            BMP581_iir_filter_coeff_t set_iir_t : 3;  // Bits 3-5: Temperature IIR LPF band filter selection
            uint8_t reserved		                : 2;  // Bits 6-7: Reserved, should be written as 0x0
        } BitField;
    } Val;
} BMP581_dsp_iir_config_t;

// OOR Count Limit (0x35)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t oor_thr_p_16					 : 1;  // Bit 0: OOR pressure threshold, bit 16
            uint8_t reserved							 : 5;  // Bits 1-5: Reserved
            BMP581_oor_cnt_limit_t cnt_lim : 2;  // Bits 6-7: OOR count limit (use enum)
        } BitField;
    } Val;
} BMP581_oor_config_t;

// Oversampling rates (0x36)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            BMP581_osr_t osr_t   : 3;  // Bits 0-2: OSR_T selection
            BMP581_osr_t osr_p   : 3;  // Bits 3-5: OSR_P selection
            uint8_t press_en     : 1;  // Bit 6: Pressure enable
            uint8_t reserved	   : 1;  // Bit 7: Reserved
        } BitField;
    } Val;
} BMP581_osr_config_t;

// ODR Configuration Register (0x37)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            BMP581_pwr_mode_t pwr_mode 			: 2;  // Bits 0-1: Power mode configuration
            BMP581_odr_sel_t  odr      			: 5;  // Bits 2-6: ODR selection
            BMP581_deep_standby_t deep_dis	: 1;  // Bit 7: Deep standby disable
        } BitField;
    } Val;
} BMP581_odr_config_t;

// Effective OSR Configuration Register (0x38)
typedef struct __attribute__((packed)) {
    union {
        uint8_t Value;
        struct __attribute__((packed)) {
            uint8_t osr_t_eff      : 3;  // Bits 0-2: Effective OSR for temperature
            uint8_t osr_p_eff      : 3;  // Bits 3-5: Effective OSR for pressure
            uint8_t reserved	     : 1;  // Bit 6: Reserved
            uint8_t odr_is_valid   : 1;  // Bit 7: ODR validity flag
        } BitField;
    } Val;
} BMP581_osr_eff_config_t;

typedef struct __attribute__((packed)) {
    //uint8_t CHIP_ID;												// BMP581_REG_CHIP_ID (0x01)
    //uint8_t CHIP_REV;												// BMP581_REG_CHIP_REV (0x02)
    BMP581_asic_status_t CHIP_STATUS;				// BMP581_REG_CHIP_STATUS (0x11)
    BMP581_host_if_config_t DRIVE_CONFIG;		// BMP581_REG_DRIVE_CONFIG (0x13)
    BMP581_int_config_t INT_CONFIG;					// BMP581_REG_INT_CONFIG (0x14)
    BMP581_int_source_t INT_SOURCE;					// BMP581_REG_INT_SOURCE (0x15)
    BMP581_fifo_config_t FIFO_CONFIG;				// BMP581_REG_FIFO_CONFIG (0x16)
    BMP581_fifo_count_t FIFO_COUNT;					// BMP581_REG_FIFO_COUNT (0x17)
    BMP581_fifo_frame_sel_t FIFO_SEL;				// BMP581_REG_FIFO_SEL (0x18)
    BMP581_sensor_data_t TEMP_PRESS;				// BMP581_REG_TEMP_DATA_XLSB - BMP581_REG_TEMP_DATA_MSB (0x1D - 0x1F) + BMP581_REG_PRESS_DATA_XLSB - BMP581_REG_PRESS_DATA_MSB (0x20 - 0x22)
    BMP581_int_status_t INT_STATUS;					// BMP581_REG_INT_STATUS (0x27)
    BMP581_status_t STATUS;									// BMP581_REG_STATUS (0x28)
    uint8_t FIFO_DATA;											// BMP581_REG_FIFO_DATA (0x29)
    BMP581_nvm_addr_t NVM_ADDR;							// BMP581_REG_NVM_ADDR (0x2B)
    uint16_t NVM_DATA;											// BMP581_REG_NVM_DATA_LSB - BMP581_REG_NVM_DATA_MSB (0x2C - 0x2D)
    BMP581_dsp_config_t DSP_CONFIG;					// BMP581_REG_DSP_CONFIG (0x30)
		BMP581_dsp_iir_config_t DSP_IIR_CONFIG;	// BMP581_REG_DSP_IIR_CONFIG (0x31)
		uint16_t OOR_PRESS_THR;									// BMP581_REG_OOR_PRESS_THR (0x32 - 0x33)
		uint8_t OOR_PRESS_RNG;									// BMP581_REG_OOR_PRESS_RNG (0x34)
		BMP581_oor_config_t OOR_CONFIG;					// BMP581_REG_OOR_CONFIG (0x35)
    BMP581_osr_config_t OSR_CONFIG;					// BMP581_REG_OSR_CONFIG (0x36)
    BMP581_odr_config_t ODR_CONFIG;					// BMP581_REG_ODR_CONFIG (0x37)
    BMP581_osr_eff_config_t OSR_EFF;				// BMP581_REG_OSR_EFF (0x38)
    //uint8_t cmd;														// BMP581_REG_CMD (0x7E)
} BMP581_registers_t;

// Function prototypes
HAL_StatusTypeDef BMP581_Init(void);
HAL_StatusTypeDef BMP581_SendCommand(BMP581_cmd_t cmd);

uint8_t BMP581_Get_CHIP_ID(void);
uint8_t BMP581_Get_CHIP_REV(void);
HAL_StatusTypeDef BMP581_Get_CHIPStatus(void);
HAL_StatusTypeDef BMP581_Set_DriveConfig(void);
HAL_StatusTypeDef BMP581_Get_DriveConfig(void);
HAL_StatusTypeDef BMP581_Set_INTConfig(void);
HAL_StatusTypeDef BMP581_Get_INTConfig(void);
HAL_StatusTypeDef BMP581_Set_INTSource(void);
HAL_StatusTypeDef BMP581_Get_INTSource(void);
HAL_StatusTypeDef BMP581_Set_FIFOConfig(void);
HAL_StatusTypeDef BMP581_Get_FIFOConfig(void);
HAL_StatusTypeDef BMP581_Get_FIFOCount(void);
HAL_StatusTypeDef BMP581_Get_FIFOFrameSel(void);
HAL_StatusTypeDef BMP581_Set_FIFOFrameSel(void);
HAL_StatusTypeDef BMP581_Get_TempPressData(BMP581_sensor_data_t *data);
HAL_StatusTypeDef BMP581_Get_INTStatus(void);
HAL_StatusTypeDef BMP581_Get_Status(void);
HAL_StatusTypeDef BMP581_Get_FIFOData(void);
HAL_StatusTypeDef BMP581_Set_NVMAddr(void);
HAL_StatusTypeDef BMP581_Get_NVMAddr(void);
HAL_StatusTypeDef BMP581_Set_NVMData(void);
HAL_StatusTypeDef BMP581_Get_NVMData(void);
HAL_StatusTypeDef BMP581_Set_DSPConfig(void);
HAL_StatusTypeDef BMP581_Get_DSPConfig(void);
HAL_StatusTypeDef BMP581_Set_DSPIIRConfig(void);
HAL_StatusTypeDef BMP581_Get_DSPIIRConfig(void);
HAL_StatusTypeDef BMP581_Set_OOR_PRESS_THR(void);
HAL_StatusTypeDef BMP581_Get_OOR_PRESS_THR(void);
HAL_StatusTypeDef BMP581_Set_OORRange(void);
HAL_StatusTypeDef BMP581_Get_OORRange(void);
HAL_StatusTypeDef BMP581_Set_OORConfig(void);
HAL_StatusTypeDef BMP581_Get_OORConfig(void);
HAL_StatusTypeDef BMP581_Set_OSRConfig(void);
HAL_StatusTypeDef BMP581_Get_OSRConfig(void);
HAL_StatusTypeDef BMP581_Set_ODRConfig(void);
HAL_StatusTypeDef BMP581_Get_ODRConfig(void);
HAL_StatusTypeDef BMP581_Get_OSREff(void);

#ifdef __cplusplus
}
#endif

#endif /* __BMP581_H */

In BMP581.c add the following code

#include "BMP581.h"
#include "i2c.h"
#include "gpio.h"

// Global instance of BMP581 registers
static BMP581_registers_t bmp581_regs;
extern volatile uint8_t i2c1_transfer_complete;

// Helper function to convert 3 bytes to a 32-bit integer
// static inline int32_t get_32bit(const uint8_t *data_ptr) {
//    return (int32_t)(data_ptr[2] << 16 | data_ptr[1] << 8 | data_ptr[0]);
//}
static inline int32_t get_32bit(const uint8_t *data_ptr) {
    return (int32_t)(*(uint32_t*)data_ptr & 0x00FFFFFF);  // Masking to keep 3 bytes
}

// I2C write function
static HAL_StatusTypeDef write(const uint8_t regAddress, const uint8_t* dataBuffer, uint8_t numBytes) {
    #ifdef USE_I2C_DMA
        i2c1_transfer_complete = 0;
        HAL_StatusTypeDef status = HAL_I2C_Mem_Write_DMA(&hi2c1, BMP581_ADDRESS, regAddress, ONE, (uint8_t *)dataBuffer, numBytes);
        if (status != HAL_OK) {
            return status;
        }
        uint32_t timeout = HAL_GetTick();
        while (!i2c1_transfer_complete) {
            if ((HAL_GetTick() - timeout) > I2C_TIMEOUT) {
                return HAL_TIMEOUT;
            }
        }
        return HAL_OK;
    #else
        return HAL_I2C_Mem_Write(&hi2c1, BMP581_ADDRESS, regAddress, ONE, (uint8_t *)dataBuffer, numBytes, I2C_TIMEOUT);
    #endif
}

// I2C read function
static HAL_StatusTypeDef read(const uint8_t regAddress, uint8_t* dataBuffer, const uint8_t numBytes) {
    #ifdef USE_I2C_DMA
        i2c1_transfer_complete = 0;
        HAL_StatusTypeDef status = HAL_I2C_Mem_Read_DMA(&hi2c1, BMP581_ADDRESS, regAddress, ONE, dataBuffer, numBytes);
        if (status != HAL_OK) {
            return status;
        }
        uint32_t timeout = HAL_GetTick();
        while (!i2c1_transfer_complete) {
            if ((HAL_GetTick() - timeout) > I2C_TIMEOUT) {
                return HAL_TIMEOUT;
            }
        }
        return HAL_OK;
    #else
        return HAL_I2C_Mem_Read(&hi2c1, BMP581_ADDRESS, regAddress, ONE, dataBuffer, numBytes, I2C_TIMEOUT);
    #endif
}

// Function to initialize the BMP581 sensor
HAL_StatusTypeDef BMP581_Init(void) {
    // Step 1: Send reset command
    if (BMP581_SendCommand(BMP581_CMD_RESET) != HAL_OK) {
        return HAL_ERROR;
    }
    HAL_Delay(5);  // Use minimal delay as per the datasheet.

    // Step 2: Read and verify the CHIP ID
    uint8_t chip_id = BMP581_Get_CHIP_ID();
    if (chip_id != BMP581_CHIP_ID_PRIM) {
        return HAL_ERROR;  // Invalid CHIP_ID
    }

    // Step 3: Read the STATUS register to check NVM readiness and errors
    if (BMP581_Get_Status() != HAL_OK) {
        return HAL_ERROR;  // Failed to read STATUS register
    }
    if (bmp581_regs.STATUS.Val.BitField.status_nvm_rdy != 1 || bmp581_regs.STATUS.Val.BitField.status_nvm_err != 0) {
        return HAL_ERROR;  // NVM not ready or there's an NVM error
    }

    // Step 4: Check Power-On Reset (POR) completion
    if (BMP581_Get_INTStatus() != HAL_OK) {
        return HAL_ERROR;  // Failed to read INT_STATUS register
    }
    if (bmp581_regs.INT_STATUS.Val.BitField.por != 1) {
        return HAL_ERROR;  // Power-on reset not complete
    }

    // Step 5: Configure the sensor settings for continuous high-accuracy mode
    bmp581_regs.OSR_CONFIG.Val.BitField.osr_t = BMP581_OSR_128X;  // Oversampling for temperature
    bmp581_regs.OSR_CONFIG.Val.BitField.osr_p = BMP581_OSR_128X;  // Oversampling for pressure
    bmp581_regs.OSR_CONFIG.Val.BitField.press_en = 1;  // Enable pressure measurement
    if (BMP581_Set_OSRConfig() != HAL_OK) {
        return HAL_ERROR;
    }

    // Step 6: Configure the IIR filters
    bmp581_regs.DSP_IIR_CONFIG.Val.BitField.set_iir_t = BMP581_IIR_COEFF_127;  // IIR filter for temperature
    bmp581_regs.DSP_IIR_CONFIG.Val.BitField.set_iir_p = BMP581_IIR_COEFF_127;  // IIR filter for pressure
    if (BMP581_Set_DSPIIRConfig() != HAL_OK) {
        return HAL_ERROR;
    }

    // Step 7: Set the output data rate (ODR) and power mode
    bmp581_regs.ODR_CONFIG.Val.BitField.odr = BMP581_ODR_5_HZ;  // Set ODR to 5Hz
    bmp581_regs.ODR_CONFIG.Val.BitField.pwr_mode = BMP581_PWRMODE_NORMAL;  // Set to normal power mode
    bmp581_regs.ODR_CONFIG.Val.BitField.deep_dis = BMP581_DEEP_DISABLED;  // Disable deep standby
    if (BMP581_Set_ODRConfig() != HAL_OK) {
        return HAL_ERROR;
    }

    // Step 8: Configure interrupts
    bmp581_regs.INT_CONFIG.Val.BitField.int_mode = BMP581_INT_MODE_PULSED;
    bmp581_regs.INT_CONFIG.Val.BitField.int_pol = BMP581_INT_POL_ACTIVE_HIGH;
    bmp581_regs.INT_CONFIG.Val.BitField.int_od = BMP581_INT_PIN_PUSH_PULL;
    bmp581_regs.INT_CONFIG.Val.BitField.int_en = BMP581_INT_ENABLE;
    if (BMP581_Set_INTConfig() != HAL_OK) {
        return HAL_ERROR;
    }

    // Step 9: Enable data-ready interrupt
    bmp581_regs.INT_SOURCE.Val.BitField.drdy_data_reg_en = BMP581_INT_ENABLE;
    bmp581_regs.INT_SOURCE.Val.BitField.fifo_full_en = BMP581_INT_DISABLE;
    bmp581_regs.INT_SOURCE.Val.BitField.fifo_ths_en = BMP581_INT_DISABLE;
    bmp581_regs.INT_SOURCE.Val.BitField.oor_p_en = BMP581_INT_DISABLE;
    if (BMP581_Set_INTSource() != HAL_OK) {
        return HAL_ERROR;
    }

    // Initialization complete
    return HAL_OK;
}

// Function to send commands to BMP581 sensor
HAL_StatusTypeDef BMP581_SendCommand(BMP581_cmd_t cmd) {
    return write(BMP581_REG_CMD, &cmd, ONE);
}

// Register functions

// REG 0x01 - CHIP ID
uint8_t BMP581_Get_CHIP_ID(void) {
    uint8_t id = 0;
    if (read(BMP581_REG_CHIP_ID, &id, ONE) == HAL_OK) {
        return id;
    }
    return 0;
}

// REG 0x02 - CHIP Revision ID
uint8_t BMP581_Get_CHIP_REV(void) {
    uint8_t rev = 0;
    if (read(BMP581_REG_REV_ID, &rev, ONE) == HAL_OK) {
        return rev;
    }
    return 0;
}

// REG 0x11 - CHIP STATUS
HAL_StatusTypeDef BMP581_Get_CHIPStatus(void) {
    return read(BMP581_REG_CHIP_STATUS, (uint8_t *)&bmp581_regs.CHIP_STATUS.Val, ONE);
}

// REG 0x13 - DRIVE CONFIG
HAL_StatusTypeDef BMP581_Set_DriveConfig(void) {
    return write(BMP581_REG_DRIVE_CONFIG, (uint8_t *)&bmp581_regs.DRIVE_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_DriveConfig(void) {
    return read(BMP581_REG_DRIVE_CONFIG, (uint8_t *)&bmp581_regs.DRIVE_CONFIG.Val, ONE);
}

// REG 0x14 - Interrupt Configuration
HAL_StatusTypeDef BMP581_Set_INTConfig(void) {
    return write(BMP581_REG_INT_CONFIG, (uint8_t *)&bmp581_regs.INT_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_INTConfig(void) {
    return read(BMP581_REG_INT_CONFIG, (uint8_t *)&bmp581_regs.INT_CONFIG.Val, ONE);
}

// REG 0x15 - Interrupt Source Configuration
HAL_StatusTypeDef BMP581_Set_INTSource(void) {
    return write(BMP581_REG_INT_SOURCE, (uint8_t *)&bmp581_regs.INT_SOURCE.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_INTSource(void) {
    return read(BMP581_REG_INT_SOURCE, (uint8_t *)&bmp581_regs.INT_SOURCE.Val, ONE);
}

// REG 0x16 - FIFO Configuration
HAL_StatusTypeDef BMP581_Set_FIFOConfig(void) {
    return write(BMP581_REG_FIFO_CONFIG, (uint8_t *)&bmp581_regs.FIFO_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_FIFOConfig(void) {
    return read(BMP581_REG_FIFO_CONFIG, (uint8_t *)&bmp581_regs.FIFO_CONFIG.Val, ONE);
}

// REG 0x17 - FIFO Count
HAL_StatusTypeDef BMP581_Get_FIFOCount(void) {
    return read(BMP581_REG_FIFO_COUNT, (uint8_t *)&bmp581_regs.FIFO_COUNT.Val, ONE);
}

// REG 0x18 - FIFO Frame Selection
HAL_StatusTypeDef BMP581_Get_FIFOFrameSel(void) {
    return write(BMP581_REG_FIFO_SEL, (uint8_t *)&bmp581_regs.FIFO_SEL.Val, ONE);
}

HAL_StatusTypeDef BMP581_Set_FIFOFrameSel(void) {
    return read(BMP581_REG_FIFO_SEL, (uint8_t *)&bmp581_regs.FIFO_SEL.Val, ONE);
}

// REG 0x1D - 0x1F Temperature and 0x20 - 0x22 Pressure Data
HAL_StatusTypeDef BMP581_Get_TempPressData(BMP581_sensor_data_t *data) {
    uint8_t reg_data[SIX] __attribute__((aligned(4)));  // Ensure 32-bit alignment
    if (read(BMP581_REG_TEMP_DATA_XLSB, reg_data, SIX) == HAL_OK) {
        // Convert raw temperature data
        int32_t raw_data = get_32bit(&reg_data[0]);  // Aligned access
        data->temperature = (float)raw_data / TEMP_COEFF;

        // Convert raw pressure data
        raw_data = get_32bit(&reg_data[3]);  // Aligned access
        data->pressure = (float)raw_data / PRESS_COEFF;
        return HAL_OK;
    }
    return HAL_ERROR;
}

// REG 0x27 - Interrupt Status
HAL_StatusTypeDef BMP581_Get_INTStatus(void) {
    return read(BMP581_REG_INT_STATUS, (uint8_t *)&bmp581_regs.INT_STATUS.Val, ONE);
}

// REG 0x28 - Status Register
HAL_StatusTypeDef BMP581_Get_Status(void) {
    return read(BMP581_REG_STATUS, (uint8_t *)&bmp581_regs.STATUS.Val, ONE);
}

// REG 0x29 - FIFO Data
HAL_StatusTypeDef BMP581_Get_FIFOData(void) {
    return read(BMP581_REG_FIFO_DATA, (uint8_t *)&bmp581_regs.FIFO_DATA, ONE);
}

// REG 0x2B - NVM Address
HAL_StatusTypeDef BMP581_Set_NVMAddr(void) {
    return write(BMP581_REG_NVM_ADDR, (uint8_t *)&bmp581_regs.NVM_ADDR.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_NVMAddr(void) {
    return read(BMP581_REG_NVM_ADDR, (uint8_t *)&bmp581_regs.NVM_ADDR.Val, ONE);
}

// REG 0x2C - 0x2D - NVM Data
HAL_StatusTypeDef BMP581_Set_NVMData(void) {
    return write(BMP581_REG_NVM_DATA_LSB, (uint8_t *)&bmp581_regs.NVM_DATA, TWO);
}

HAL_StatusTypeDef BMP581_Get_NVMData(void) {
    return read(BMP581_REG_NVM_DATA_LSB, (uint8_t *)&bmp581_regs.NVM_DATA, TWO);
}

// REG 0x30 - DSP Configuration
HAL_StatusTypeDef BMP581_Set_DSPConfig(void) {
    return write(BMP581_REG_DSP_CONFIG, (uint8_t *)&bmp581_regs.DSP_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_DSPConfig(void) {
    return read(BMP581_REG_DSP_CONFIG, (uint8_t *)&bmp581_regs.DSP_CONFIG.Val, ONE);
}

// REG 0x31 - DSP IIR Configuration
HAL_StatusTypeDef BMP581_Set_DSPIIRConfig(void) {
    return write(BMP581_REG_DSP_IIR, (uint8_t *)&bmp581_regs.DSP_IIR_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_DSPIIRConfig(void) {
    return read(BMP581_REG_DSP_IIR, (uint8_t *)&bmp581_regs.DSP_IIR_CONFIG.Val, ONE);
}

// REG 0x32 - 0x33 - OOR Pressure Threshold
HAL_StatusTypeDef BMP581_Set_OOR_PRESS_THR(void) {
    return write(BMP581_REG_OOR_THR_P_LSB, (uint8_t *)&bmp581_regs.OOR_PRESS_THR, TWO);
}

HAL_StatusTypeDef BMP581_Get_OOR_PRESS_THR(void) {
    return read(BMP581_REG_OOR_THR_P_LSB, (uint8_t *)&bmp581_regs.OOR_PRESS_THR, TWO);
}

// REG 0x34 - OOR Range
HAL_StatusTypeDef BMP581_Set_OORRange(void) {
    return write(BMP581_REG_OOR_RANGE, (uint8_t *)&bmp581_regs.OOR_PRESS_RNG, ONE);
}

HAL_StatusTypeDef BMP581_Get_OORRange(void) {
    return read(BMP581_REG_OOR_RANGE, (uint8_t *)&bmp581_regs.OOR_PRESS_RNG, ONE);
}

// REG 0x35 - OOR Configuration
HAL_StatusTypeDef BMP581_Set_OORConfig(void) {
    return write(BMP581_REG_OOR_CONFIG, (uint8_t *)&bmp581_regs.OOR_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_OORConfig(void) {
    return read(BMP581_REG_OOR_CONFIG, (uint8_t *)&bmp581_regs.OOR_CONFIG.Val, ONE);
}

// REG 0x36 - OSR Configuration
HAL_StatusTypeDef BMP581_Set_OSRConfig(void) {
    return write(BMP581_REG_OSR_CONFIG, (uint8_t *)&bmp581_regs.OSR_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_OSRConfig(void) {
    return read(BMP581_REG_OSR_CONFIG, (uint8_t *)&bmp581_regs.OSR_CONFIG.Val, ONE);
}

// REG 0x37 - ODR Configuration
HAL_StatusTypeDef BMP581_Set_ODRConfig(void) {
    return write(BMP581_REG_ODR_CONFIG, (uint8_t *)&bmp581_regs.ODR_CONFIG.Val, ONE);
}

HAL_StatusTypeDef BMP581_Get_ODRConfig(void) {
    return read(BMP581_REG_ODR_CONFIG, (uint8_t *)&bmp581_regs.ODR_CONFIG.Val, ONE);
}

// REG 0x38 - Effective OSR
HAL_StatusTypeDef BMP581_Get_OSREff(void) {
    return read(BMP581_REG_OSR_EFF, (uint8_t *)&bmp581_regs.OSR_EFF.Val, ONE);
}

Comments powered by CComment