Foreword
这周选错传感器了,把 LPS22HB 选成 LPS22HH 了,文档白写了😫
就来更个 CSDN 吧,不然亏大了。
LPS22HB 和 LPS22HH 的异同
先讲讲他们的异同点吧
相同点
- 地址是一样的(所以我看着 HH 的文档跑通了 HB 的传感器……)
- 基础配置以及数据寄存器地址一样(FIFO 以及 Interrupt 功能位不一致)
- 读取的数据都是气压和温度,位数一样
- 气压测量范围一样
- 都支持 SPI 和 I2C 通讯
- 都支持 FIFO 和 Interrupt
- 都支持设置参考气压值
不同点
- WHO_AM_I 不一样,差了一位(发现 WHO_AM_I 对不上的时候我竟然觉得是文档写错了😑)
- LPS22HH 支持 I3C 通讯
- LPS22HH 支持更高的采样频率
- LPS22HH 内部 FIFO 更大,FIFO 模式有区别
- LPS22HH 有专门的 FIFO 数据读取寄存器
LPS22HH 压力传感器
主控芯片:MM32F3277
传感器:LPS22HH 压力传感器
通讯方式:I2C
开发环境:IAR 7.80.4
Features
- Embedded temperature compensation
- 24-bit pressure data output
- SPI, I2C or MIPI I3C interfaces
- Embedded FIFO
- Interrupt functions: Data-Ready, FIFO flags, pressure thresholds
Applications
- Altimeters and barometers for portable devices
- GPS applications
- Weather station equipment
- Sport watches
- e-cigarettes
- Drones
- Gas metering
Pin
-
VDD_IO: Power Supply
-
SCL / SPC: SCL for I2C and I3C serial clock; SPC for SPI serial port clock
-
RES: Connected to GND
-
SDA / SDI / SDI or SDO: SDA for I2C and I3C serial data; SDI for 4-wire SPI serial data input; SDI or SDO for 3-wire SPI serial data input or output
-
SA0 / SDO: SA0 for I2C and I3C LSB address; SDO for 4-wire SPI serial data output
-
CS: interface selection 0 for SPI; 1 for I2C / I3C
-
INT_DRDY: Interrupt or Data-Ready; Floating(Internal pull-down) for I2C and I3C; VDD_IO for I3C only
-
GND
-
GND
-
VDD
在 MB-018 中,LPS22HH 连接 I2C,CS 接 VDD,SA0 接地 LSB = 0,INT_DRDY floating,I3C_DISABLE 置 1
LPS22HH Address
SA0 管脚决定了地址 LSB 位的高低,这样主控就可以连两个 LPS22HH 传感器,从地址不会冲突
// LPS22HB Address
#define SLAVE_ADDRESS_SA0 0x00
#define SLAVE_ADDRESS (0x5C | SLAVE_ADDRESS_SA0) // 0x5C
#define SLAVE_ADDRESS_WRITE SLAVE_ADDRESS << 1 // 0xB8
#define SLAVE_ADDRESS_READ (SLAVE_ADDRESS << 1) | 0x01 // 0xB9
I2C 对 LPS22HH 进行读写
I2C 读写方式及原理可见「Rose Island」MM32F3277 I2C 访问 HTS221 温湿度传感器
Master write data to Slave
Steps:
-
Master 发送 START 信号(SCL hold high, SDA high to low)
-
Master 发送 Slave 的 7 位地址 + 写信号
-
Slave 进行地址匹配,匹配成功回应 SAK
-
Master 发送 SubAddress,即 Slave 内部寄存器地址
通过
CTRL_REG2
中的IF_ADD_INC
位决定 SubAddr 地址是否自增,即是否可以连续操作多个寄存器,该位默认为高#define LPS22HH_CTRL_REG1 0x10 LPS22HH_Reg_Write(I2Cx, LPS22HH_CTRL_REG1, buffer, 1)
-
Slave 应答 SubAddr
-
Master 发送 DATA,Slave 应答 SAK
-
Master 发送完后,产生 STOP 信号(SCL hold high, SDA low to high)
Master read data from Slave
Steps:
- Master 发送 START 信号(SCL hold high, SDA high to low)
- Master 发送 Slave 的 7 位地址 + 写信号
- Slave 进行地址匹配,匹配成功回应 SAK
- Master 发送 SubAddress,即 Slave 内部寄存器地址,操作同上
- Slave 应答 SubAddr
- Master 发送 RESTART 信号,重新发送 Slave 的 7 位地址 + 读信号,Slave 回应 SAK
- Slave 发送 Data,Master 应答 MAK
- Master 接收最后一个数据后,不应答 NMAK,产生 STOP 信号(SCL hold high, SDA lowto high)
Calculation Function
-
Pressure Calculation
从以下三个寄存器中读取压力数据:
PRESS_OUT_H
/PRESS_OUT_L
/PRESS_OUT_XL
;如果用了传感器内部 FIFO,则读
FIFO_DATA_OUT_PRESS_H
/FIFO_DATA_OUT_PRESS_L
/FIFO_DATA_OUT_PRESS_XL
P r e s s u r e ( h P a ) = ( P R E S S _ O U T _ H < < 16 ) & ( P R E S S _ O U T _ L < < 8 ) & ( P R E S S _ O U T _ X L ) 4096 Pressure(hPa) = \frac{(PRESS\_OUT\_H << 16)\ \ \&\ \ (PRESS\_OUT\_L << 8)\ \ \&\ \ (PRESS\_OUT\_XL)}{4096} Pressure(hPa)=4096(PRESS_OUT_H<<16) & (PRESS_OUT_L<<8) & (PRESS_OUT_XL) -
Temperature Calculation
从以下两个寄存器中读取压力数据:
TEMP_OUT_H
/TEMP_OUT_L
;如果用了传感器内部 FIFO,则读
FIFO_DATA_OUT_TEMP_H
/FIFO_DATA_OUT_TEMP_L
T e m p e r a t u r e ( d e g C ) = ( T E M P _ O U T _ H < < 8 ) & ( T E M P _ O U T _ L ) 100 Temperature(degC)=\frac{(TEMP\_OUT\_H << 8)\ \ \&\ \ (TEMP\_OUT\_L)}{100} Temperature(degC)=100(TEMP_OUT_H<<8) & (TEMP_OUT_L)
Embedded FIFO
128 个 40 位数据 FIFO 用于存储压力和温度值,在主控需要读取时唤醒传感器,从 FIFO 取出数据。启用 FIFO 后依旧可以从标准寄存器中读取数据。
6 种模式:
-
Bypass mode
FIFO 未启用。如果需要切换 FIFO mode,需要先设置为 Bypass mode,再设置新的 FIFO mode。
-
FIFO mode
启用 FIFO,数据会存入 FIFO 直到 FIFO 满。FIFO 默认深度是 128,用户可以通过配置
FIFO_WTM[6:0]
设定 FIFO 深度。FIFO 满后,需要切换回 Bypass mode 再重启 FIFO mode。
-
Continuous (Dynamic-Stream) mode
启用 FIFO,环形队列。新的数据样本会放入 FIFO 触发读取。这种方式用于当数据读取周期不能满足 1/ODR 的时候。
同时也可以使用
INT_F_WTM
中断,当 FIFO 满的时候,下一个数据触发读取 FIFO,FIFO 清空重新装数据。 -
Bypass to FIFO mode
使用该模式需要启用中断。根据中断状态
INT_SOURCE
中的IA
决定 mode,IA
= 0 时为 Bypass mode,IA
= 1 时为 FIFO mode。 -
Bypass to Continuous (Dynamic-Stream) mode
使用该模式需要启用中断。根据中断状态
INT_SOURCE
中的IA
决定 mode,IA
= 0 时为 Bypass mode,IA
= 1 时为 Continuous (Dynamic-Stream) mode。 -
Continuous (Dynamic-Stream) to FIFO mode
使用该模式需要启用中断。根据中断状态
INT_SOURCE
中的IA
决定 mode,IA
= 0 时为 Continuous (Dynamic-Stream) mode,IA
= 1 时为 FIFO mode。
Register Map
-
INTERRUPT_CFG
Reg Address is 0x0B, R/W and default is 0x00
-
PHE
: 当气压比设定的标准线高时产生中断,标准线由用户定义,存储在THS_P
寄存器中 -
PLE
: 当气压比设定的标准线低时产生中断,标准线由用户定义,存储在THS_P
寄存器中 -
LIR
: 是否锁存中断请求至INT_SOURCE
寄存器 -
DIFF_EN
: 中断使能 -
RESET_AZ
: Reset AUTOZERO function -
AUTOZERO
: Enable AUTOZERO functionAUTOZERO
置 1 后,读取的数据会作为参考值存入REF_P
寄存器,之后该位自动清 0,如果要取消该参考值,需要对RESET_AZ
位置 1P_DIFF_IN = measured pressure - REF_P (该值用于产生中断)
PRESS_OUT = measured pressure - REF_P
如果使用了
AUTOZERO
,PHE
比较的是 P_DIFF_IN 和THS_P
-
RESET_ARP
: Reset AUTOREFP function -
AUTOREFP
: Enable AUTOREFP functionAUTOREFP
置 1 后,读取的数据会作为参考值存入REF_P
寄存器,之后该位自动清 0,如果要取消该参考值,需要对RESET_ARP
位置 1与
AUTOZERO
不同的是,PRESS_OUT
输出的是测量值,而不是与参考值的差值P_DIFF_IN = measured pressure - REF_P (该值用于产生中断)
PRESS_OUT = measured pressure
-
-
**THS_P_L / THS_P_H **
Reg Address is 0x0C and 0x0D, R/W and default is 0x00
该 15 位的值用于和测量出的压力数据进行比较,产生中断。
若要产生中断,需要将
INTERRUPT_CFG
中DIFF_EN
/PHE
/PLE
位使能THS_P(15-bit unsigned) = Desired interrupt threshold(hPa) × 16
-
IF_CTRL
Reg Address is 0x0E, R/W and default is 0x00
I2C_DISABLE
: Set 0 to enable I2C; Set 1 to disable I2CI3C_DISABLE
: Set 0 to enable I3C; Set 1 to disable I3CPD_DIS_INT1
: 置 0 时 INT1 管脚下拉;置 1 时 INT1 管脚不下拉SDO_PU_EN
: 置 0 时 SDO 管脚不上拉;置 1 时 SDO 管脚上拉SDA_PU_EN
: 置 0 时 SDA 管脚不上拉;置 1 时 SDA 管脚上拉INT_EN_I3C
: 置 0 时 INT1 管脚不使能 I3C;置 0 时 INT1 管脚使能 I3C
-
WHO_AM_I
Reg Address is 0x0F, read only and default is 0xB3
// LPS22HH Device ID #define DEVICE_ID_WHO_AM_I 0xB3
-
CTRL_REG1
Reg Address is 0x10, R/W and default is 0x00
SIM
: 置 0 为 4 线 SPI;置 1 为 3 线 SPIBDU
: 置 0 为连续更新 MSB 和 LSB 的数据;置 1 为只有当 MSB 和 LSB 都被读取了之后再更新数据,建议置 1LPFP_CFG
: 如果低通滤波器未使能,bandwith = ODR / 2;如果低通滤波器使能且该位为 0,bandwith = ODR / 9;如果低通滤波器使能且该位为 1,bandwith = ODR / 20EN_LPFP
: 是否使能低通滤波器ODR
: 0x00 为 one-shot 模式,设备为 Power-down mode,配合CFGR_REG2
中的ONE_SHOT
位触发一次读取;其他情况下设备为 Continuous mode,根据频率连续读取数据
-
CTRL_REG2
Reg Address is 0x11, R/W and default is 0x00
ONE_SHOT
: 触发 One_Shot,CFGR_REG1
中的ODR
位需要是 0x00,硬件清零LOW_NOISE_EN
: 置 0 为 low-current 模式;置 1 为 low-noise 模式,此时 ODR < 100HzSWRESET
: 置 1 为软件重启,硬件清零IF_ADD_INC
: I2C / SPI 模式下操作寄存器时,地址自增PP_OD
: interrupt 管脚配置,置 0 为推挽输出;置 1 为开漏输出INT_H_L
: 置 0 为 interrupt 高有效;置 1 为低有效BOOT
: 置 1 为 reboot,硬件清零
-
CTRL_REG3
Reg Address is 0x12, R/W and default is 0x00
INT_S
: INT_DRDY 管脚输出,00 为 Data Signal,01 为 Pressure high 中断,10 为 Pressure Low 中断,11 为 Pressure High or Low 中断DRDY
: INT_DRDY 管脚输出 Data ready signalINT_F_OVR
: INT_DRDY 管脚输出 FIFO overrun statusINT_F_WTM
: INT_DRDY 管脚输出 FIFO threshold statusINT_F_FULL
: INT_DRDY 管脚输出 FIFO full flag
-
FIFO_CTRL
Reg Address is 0x13, R/W and default is 0x00
-
F_MODE
/TRIG_MODES
TRIG_MODES F_MODE MODE X 00 Bypass mode 0 01 FIFO mode 0 1X Continuous (Dynamic-Stream) mode 1 01 Bypass to FIFO mode 1 10 Bypass to Continuous (Dynamic-Stream) mode 1 11 Continuous (Dynamic-Stream) to FIFO mode -
STOP_ON_WTM
: 如果设置了FIFO_WTM
的WTM
位,FIFO 中的数量到达 watermark level 的时候,FIFO 为满
-
-
FIFO_WTM
Reg Address is 0x14, R/W and default is 0x00
WTM
为 FIFO watermark level -
REF_P_L
/REF_P_H
Reg Address is 0x15 / 0x16, read only and default is 0x00
当
INTERRUPT_CFG
中AUTOZERO
和AUTOREFP
使能时,需要用到参考气压值 -
RPDS_L
/RPDS_H
Reg Address is 0x18 / 0x19, read only and default is 0x00
用于焊接后的压力偏移量校准
-
INT_SOURCE
Reg Address is 0x24, read only and default is 0x00
PH
: high differential pressure eventPL
: low differential pressure eventIA
: one or more interrupt event generatedBOOT_ON
: boot phase running
-
FIFO_STATUS1
Reg Address is 0x25, read only and default is 0x00
FSS
: 0x00 为 FIFO 空;0x80 为 FIFO满 -
FIFO_STATUS2
Reg Address is 0x26, read only and default is 0x00
FIFO_FULL_IA
: FIFO 满但未溢出FIFO_OVR_IA
: FIFO 满且溢出FIFO_WTM_IA
: FIFO 大于等于 watermark level
-
STATUS
Reg Address is 0x27, read only and default is 0x00
跟着
ODR
频率更新P_DA
: 有新的压力数据了T_DA
: 有新的温度数据了P_OR
: 压力数据溢出,旧的数据被替换T_OR
: 温度数据溢出,旧的数据被替换
-
PRESS_OUT_XL
/PRESS_OUT_L
/PRESS_OUT_H
Reg Address is 0x28 / 0x29 / 0x2A , read only and default is 0x00
输出的是与
RPDS
的差值 -
TEMP_OUT_L
/TEMP_OUT_H
Reg Address is 0x2B / 0x2C , read only and default is 0x00
-
FIFO_DATA_OUT_PRESS_XL
/FIFO_DATA_OUT_PRESS_L
/FIFO_DATA_OUT_PRESS_H
Reg Address is 0x78 / 0x79 / 0x7A , read only and default is 0x00
-
FIFO_DATA_OUT_TEMP_L
/FIFO_DATA_OUT_TEMP_H
Reg Address is 0x7B / 0x7C , read only and default is 0x00
Code
实现 LPS22HH 数据读取
-
lps22hh.h
#ifndef __LPS22HH_H_ #define __LPS22HH_H_ typedef enum { LPS22HH_OK = (uint8_t)0, LPS22HH_ERROR = !LPS22HH_OK } LPS22HH_Error_Typedef; typedef enum { LPS22HH_DISABLE = (uint8_t)0, LPS22HH_ENABLE = !LPS22HH_DISABLE } LPS22HH_State_Typedef; /// @defgroup HPS22HH Interrupts Definition /// @{ #define LPS22HH_IT_PHE 0x01 #define LPS22HH_IT_PLE 0x02 /// @} /// @defgroup HPS22HH Interrupt Mode Definition /// @{ #define LPS22HH_IT_MODE_RESETAZ 0x10 #define LPS22HH_IT_MODE_AUTOZERO 0x20 #define LPS22HH_IT_MODE_RESETARP 0x40 #define LPS22HH_IT_MODE_AUTOREFP 0x80 /// @} /// @defgroup LPS22HH Statusflags definition /// @{ #define LPS22HH_ITS_PH_FLAG 0x01 #define LPS22HH_ITS_PL_FLAG 0x02 #define LPS22HH_ITS_IA_FLAG 0x04 /// @} /// @defgroup LPS22HH Output data rate /// @{ #define LPS22HH_OUTPUT_DATA_ONESHOT 0x00 #define LPS22HH_OUTPUT_DATA_RATE_1 0x01 #define LPS22HH_OUTPUT_DATA_RATE_10 0x02 #define LPS22HH_OUTPUT_DATA_RATE_25 0x03 #define LPS22HH_OUTPUT_DATA_RATE_50 0x04 #define LPS22HH_OUTPUT_DATA_RATE_75 0x05 #define LPS22HH_OUTPUT_DATA_RATE_100 0x06 #define LPS22HH_OUTPUT_DATA_RATE_200 0x07 /// @} /// @defgroup LPS22HH FIFO mode /// @{ #define LPS22HH_FIFO_MODE_BYPASS 0x00 #define LPS22HH_FIFO_MODE_FIFO 0x01 #define LPS22HH_FIFO_MODE_CONTINUOUS 0x02 #define LPS22HH_FIFO_MODE_BYPASS_2_FIFO 0x05 #define LPS22HH_FIFO_MODE_BYPASS_2_CONTINUOUS 0x06 #define LPS22HH_FIFO_MODE_CONTINUOUS_2_FIFO 0x07 /// @} #ifdef _LPS22HH_C_ // LPS22HH register subAddr #define LPS22HH_INTERRUPT_CFG 0x0B // Interrupt register #define LPS22HH_THS_P_L 0x0C // Pressure threshold registers #define LPS22HH_THS_P_H 0x0D // Pressure threshold registers #define LPS22HH_IF_CTRL 0x0E // Interface control register #define LPS22HH_WHO_AM_I 0x0F // Who am I #define LPS22HH_CTRL_REG1 0x10 // Control registers #define LPS22HH_CTRL_REG2 0x11 // Control registers #define LPS22HH_CTRL_REG3 0x12 // Control registers #define LPS22HH_FIFO_CTRL 0x13 // FIFO configuration register #define LPS22HH_FIFO_WTM 0x14 // FIFO watermark level #define LPS22HH_REF_P_L 0x15 // Reference pressure registers #define LPS22HH_REF_P_H 0x16 // Reference pressure registers #define LPS22HH_RPDS_L 0x18 // Pressure offset registers #define LPS22HH_RPDS_H 0x19 // Pressure offset registers #define LPS22HH_INT_SOURCE 0x24 // Interrupt register #define LPS22HH_FIFO_STATUS1 0x25 // FIFO status registers #define LPS22HH_FIFO_STATUS2 0x26 // FIFO status registers #define LPS22HH_STATUS 0x27 // Status register #define LPS22HH_PRESS_OUT_XL 0x28 // Pressure output registers #define LPS22HH_PRESS_OUT_L 0x29 // Pressure output registers #define LPS22HH_PRESS_OUT_H 0x2A // Pressure output registers #define LPS22HH_TEMP_OUT_L 0x2B // Temperature output registers #define LPS22HH_TEMP_OUT_H 0x2C // Temperature output registers #define LPS22HH_FIFO_DATA_OUT_PRESS_XL 0x78 // FIFO pressure output registers #define LPS22HH_FIFO_DATA_OUT_PRESS_L 0x79 // FIFO pressure output registers #define LPS22HH_FIFO_DATA_OUT_PRESS_H 0x7A // FIFO pressure output registers #define LPS22HH_FIFO_DATA_OUT_TEMP_L 0x7B // FIFO temperature output registers #define LPS22HH_FIFO_DATA_OUT_TEMP_H 0x7C // FIFO temperature output registers // LPS22HH Address #define SLAVE_ADDRESS_SA0 0x00 #define SLAVE_ADDRESS (0x5C | SLAVE_ADDRESS_SA0) // 0x5C #define SLAVE_ADDRESS_WRITE SLAVE_ADDRESS << 1 // 0xB8 #define SLAVE_ADDRESS_READ (SLAVE_ADDRESS << 1) | 0x01 // 0xB9 // LPS22HH Device ID #define DEVICE_ID_WHO_AM_I 0xB3 // LPS22HH_INTERRUPT_CFG #define LPS22HH_ITC_PHE_POS (0) #define LPS22HH_ITC_PHE (0x01 << LPS22HH_ITC_PHE_POS) #define LPS22HH_ITC_PLE_POS (1) #define LPS22HH_ITC_PLE (0x01 << LPS22HH_ITC_PLE_POS) #define LPS22HH_ITC_LIR_POS (2) #define LPS22HH_ITC_LIR (0x01 << LPS22HH_ITC_LIR_POS) #define LPS22HH_ITC_DIFF_EN_POS (3) #define LPS22HH_ITC_DIFF_EN (0x01 << LPS22HH_ITC_DIFF_EN_POS) #define LPS22HH_ITC_RESET_AZ_POS (4) #define LPS22HH_ITC_RESET_AZ (0x01 << LPS22HH_ITC_RESET_AZ_POS) #define LPS22HH_ITC_AUTOZERO_POS (5) #define LPS22HH_ITC_AUTOZERO (0x01 << LPS22HH_ITC_AUTOZERO_POS) #define LPS22HH_ITC_RESET_ARP_POS (6) #define LPS22HH_ITC_RESET_ARP (0x01 << LPS22HH_ITC_RESET_ARP_POS) #define LPS22HH_ITC_AUTOREFP_POS (7) #define LPS22HH_ITC_AUTOREFP (0x01 << LPS22HH_ITC_AUTOREFP_POS) // LPS22HH_IF_CTRL #define LPS22HH_IFC_I2C_DIS_POS (0) #define LPS22HH_IFC_I2C_DIS (0x01 << LPS22HH_IFC_I2C_DIS_POS) #define LPS22HH_IFC_I3C_DIS_POS (1) #define LPS22HH_IFC_I3C_DIS (0x01 << LPS22HH_IFC_I3C_DIS_POS) #define LPS22HH_IFC_PD_DIS_INT_POS (2) #define LPS22HH_IFC_PD_DIS_INT (0x01 << LPS22HH_IFC_PD_DIS_INT_POS) #define LPS22HH_IFC_SDO_PU_EN_POS (3) #define LPS22HH_IFC_SDO_PU_EN (0x01 << LPS22HH_IFC_SDO_PU_EN_POS) #define LPS22HH_IFC_SDA_PU_EN_POS (4) #define LPS22HH_IFC_SDA_PU_EN (0x01 << LPS22HH_IFC_SDA_PU_EN_POS) #define LPS22HH_IFC_INT_EN_I3C_POS (7) #define LPS22HH_IFC_INT_EN_I3C (0x01 << LPS22HH_IFC_INT_EN_I3C_POS) // LPS22HH_CTRL_REG1 #define LPS22HH_CR1_SIM_POS (0) #define LPS22HH_CR1_SIM (0x01U << LPS22HH_CR1_SIM_POS) #define LPS22HH_CR1_BDU_POS (1) #define LPS22HH_CR1_BDU (0x01U << LPS22HH_CR1_BDU_POS) #define LPS22HH_CR1_LPFP_CFG_POS (2) #define LPS22HH_CR1_LPFP_CFG (0x01U << LPS22HH_CR1_LPFP_CFG_POS) #define LPS22HH_CR1_EN_LPFP_POS (3) #define LPS22HH_CR1_EN_LPFP (0x01U << LPS22HH_CR1_EN_LPFP_POS) #define LPS22HH_CR1_ODR_POS (4) #define LPS22HH_CR1_ODR_ONE_SHOT (0x00U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_1 (0x01U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_10 (0x02U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_25 (0x03U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_50 (0x04U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_75 (0x05U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_100 (0x06U << LPS22HH_CR1_ODR_POS) #define LPS22HH_CR1_ODR_200 (0x07U << LPS22HH_CR1_ODR_POS) // LPS22HH_CTRL_REG2 #define LPS22HH_CR2_ONE_SHOT_POS (0) #define LPS22HH_CR2_ONE_SHOT (0x01U << LPS22HH_CR2_ONE_SHOT_POS) #define LPS22HH_CR2_LOW_NOISE_EN_POS (1) #define LPS22HH_CR2_LOW_NOISE_EN (0x01U << LPS22HH_CR2_LOW_NOISE_EN_POS) #define LPS22HH_CR2_SWRESET_POS (2) #define LPS22HH_CR2_SWRESET (0x01U << LPS22HH_CR2_SWRESET_POS) #define LPS22HH_CR2_IF_ADD_INC_POS (4) #define LPS22HH_CR2_IF_ADD_INC (0x01U << LPS22HH_CR2_IF_ADD_INC_POS) #define LPS22HH_CR2_PP_OD_POS (5) #define LPS22HH_CR2_PP_OD (0x01U << LPS22HH_CR2_PP_OD_POS) #define LPS22HH_CR2_INT_H_L_POS (6) #define LPS22HH_CR2_INT_H_L (0x01U << LPS22HH_CR2_INT_H_L_POS) #define LPS22HH_CR2_BOOT_POS (7) #define LPS22HH_CR2_BOOT (0x01U << LPS22HH_CR2_BOOT_POS) // LPS22HH_CTRL_REG3 #define LPS22HH_CR3_INT_S_POS (0) #define LPS22HH_CR3_INT_S_DATA_SIG (0x00U << LPS22HH_CR3_INT_S_POS) #define LPS22HH_CR3_INT_S_PH (0x01U << LPS22HH_CR3_INT_S_POS) #define LPS22HH_CR3_INT_S_PL (0x02U << LPS22HH_CR3_INT_S_POS) #define LPS22HH_CR3_INT_S_PHL (0x03U << LPS22HH_CR3_INT_S_POS) #define LPS22HH_CR3_DRDY_POS (2) #define LPS22HH_CR3_DRDY (0x00U << LPS22HH_CR3_DRDY_POS) #define LPS22HH_CR3_INT_F_OVR_POS (3) #define LPS22HH_CR3_INT_F_OVR (0x01U << LPS22HH_CR3_INT_F_OVR_POS) #define LPS22HH_CR3_INT_F_WTM_POS (4) #define LPS22HH_CR3_INT_F_WTM (0x01U << LPS22HH_CR3_INT_F_WTM_POS) #define LPS22HH_CR3_INT_F_FULL_POS (5) #define LPS22HH_CR3_INT_F_FULL (0x01U << LPS22HH_CR3_INT_F_FULL_POS) // LPS22HH_FIFO_CTRL #define LPS22HH_FC_MODE_POS (0) #define LPS22HH_FC_BYPASS (0x00U << LPS22HH_FC_MODE_POS) #define LPS22HH_FC_FIFO (0x01U << LPS22HH_FC_MODE_POS) #define LPS22HH_FC_CONTINUOUS (0x02U << LPS22HH_FC_MODE_POS) #define LPS22HH_FC_BYPASS_2_FIFO (0x05U << LPS22HH_FC_MODE_POS) #define LPS22HH_FC_BYPASS_2_CONTINUOUS (0x06U << LPS22HH_FC_MODE_POS) #define LPS22HH_FC_CONTINUOUS_2_FIFO (0x07U << LPS22HH_FC_MODE_POS) #define LPS22HH_FC_STOP_ON_WTM_POS (3) #define LPS22HH_FC_STOP_ON_WTM (0x01 << LPS22HH_FC_STOP_ON_WTM_POS) // LPS22HH_INT_SOURCE #define LPS22HH_ITS_PH_POS (0) #define LPS22HH_ITS_PH (0x01 << LPS22HH_ITS_PH_POS) #define LPS22HH_ITS_PL_POS (1) #define LPS22HH_ITS_PL (0x01 << LPS22HH_ITS_PL_POS) #define LPS22HH_ITS_IA_POS (2) #define LPS22HH_ITS_IA (0x01 << LPS22HH_ITS_IA_POS) // LPS22HH_FIFO_STATUS2 #define LPS22HH_FSTA_FULL_IA_POS (0) #define LPS22HH_FSTA_FULL_IA (0x01 << LPS22HH_FSTA_FULL_IA_POS) #define LPS22HH_FSTA_OVR_IA_POS (1) #define LPS22HH_FSTA_OVR_IA (0x01 << LPS22HH_FSTA_OVR_IA_POS) #define LPS22HH_FSTA_WTM_IA_POS (2) #define LPS22HH_FSTA_WTM_IA (0x01 << LPS22HH_FSTA_WTM_IA_POS) // LPS22HH_STATUS #define LPS22HH_STATUS_P_DA_POS (0) #define LPS22HH_STATUS_P_DA (1 << LPS22HH_STATUS_P_DA_POS) #define LPS22HH_STATUS_T_DA_POS (1) #define LPS22HH_STATUS_T_DA (1 << LPS22HH_STATUS_T_DA_POS) #define LPS22HH_STATUS_P_OR_POS (4) #define LPS22HH_STATUS_P_OR (1 << LPS22HH_STATUS_P_OR_POS) #define LPS22HH_STATUS_T_OR_POS (5) #define LPS22HH_STATUS_T_OR (1 << LPS22HH_STATUS_T_OR_POS) #endif LPS22HH_Error_Typedef LPS22HH_Reg_Write(I2C_TypeDef *I2Cx, u8 regAddr, u8* ptr, u16 cnt); LPS22HH_Error_Typedef LPS22HH_Reg_Read(I2C_TypeDef *I2Cx, u8 regAddr, u8* ptr, u16 cnt); u8 LPS22HH_WHO_AM_I_Get(I2C_TypeDef *I2Cx); LPS22HH_Error_Typedef LPS22HH_Software_Reset(I2C_TypeDef *I2Cx); LPS22HH_Error_Typedef LPS22HH_Init(I2C_TypeDef *I2Cx, bool oneshot, u8 frequency); LPS22HH_Error_Typedef LPS22HH_DeInit(I2C_TypeDef *I2Cx); LPS22HH_Error_Typedef LPS22HH_PRESS_OUT_Get(I2C_TypeDef *I2Cx, int32_t *P_OUT); LPS22HH_Error_Typedef LPS22HH_TEMP_OUT_Get(I2C_TypeDef *I2Cx, int16_t *T_OUT); LPS22HH_Error_Typedef LPS22HH_Pressure_Calculation(I2C_TypeDef *I2Cx, int32_t *value); LPS22HH_Error_Typedef LPS22HH_Temperature_Calculation(I2C_TypeDef *I2Cx, int16_t *value); LPS22HH_Error_Typedef LPS22HH_Calculation(I2C_TypeDef *I2Cx, int32_t *p_value, int16_t *t_value, bool oneshot); void LPS22HH_Altitude_Calculation(int32_t *p_value); #endif
-
lps22hh.c
LPS22HH_Error_Typedef LPS22HH_Reg_Write(I2C_TypeDef *I2Cx, u8 regAddr, u8* ptr, u16 cnt) { Sensor_Write(I2Cx, SLAVE_ADDRESS_WRITE, regAddr, ptr, cnt); return LPS22HH_OK; } LPS22HH_Error_Typedef LPS22HH_Reg_Read(I2C_TypeDef *I2Cx, u8 regAddr, u8* ptr, u16 cnt) { Sensor_Read(I2Cx, SLAVE_ADDRESS_READ, regAddr, ptr, cnt); return LPS22HH_OK; } u8 LPS22HH_WHO_AM_I_Get(I2C_TypeDef *I2Cx) { u8 device_id; if(LPS22HH_Reg_Read(I2Cx, LPS22HH_WHO_AM_I, &device_id, 1)) return LPS22HH_ERROR; return device_id; } LPS22HH_Error_Typedef LPS22HH_Software_Reset(I2C_TypeDef *I2Cx) { u8 swreset = 0x04; if(LPS22HH_Reg_Read(I2Cx, LPS22HH_CTRL_REG2, &swreset, 1)) return LPS22HH_ERROR; return LPS22HH_OK; } // LPS22HH_Error_Typedef LPS22HH_Init(I2C_TypeDef *I2Cx, bool oneshot, u8 frequency) { u8 buffer[3] = {0, 0, 0}; if(LPS22HH_WHO_AM_I_Get(I2Cx) == DEVICE_ID_WHO_AM_I){ buffer[0] = LPS22HH_IFC_I3C_DIS; // Disable I3C in IF_CTRL if(LPS22HH_Reg_Write(I2Cx, LPS22HH_IF_CTRL, buffer, 1)) return LPS22HH_ERROR; if(oneshot){ buffer[0] = LPS22HH_CR1_BDU | LPS22HH_CR1_ODR_ONE_SHOT; // Set BDU and ODR in CTRL_REG1 }else{ buffer[0] = LPS22HH_CR1_BDU | (frequency << LPS22HH_CR1_ODR_POS); // Set BDU and ODR in CTRL_REG1 } buffer[1] = LPS22HH_CR2_IF_ADD_INC; // Set ONESHOT and AUTOINC in CTRL_REG1 buffer[2] = 0x00; // Clear CTRL_REG3 if(LPS22HH_Reg_Write(I2Cx, LPS22HH_CTRL_REG1, buffer, 3)) return LPS22HH_ERROR; return LPS22HH_OK; }else{ return LPS22HH_ERROR; } } // LPS22HH_Error_Typedef LPS22HH_DeInit(I2C_TypeDef *I2Cx) { u8 buffer[4] = {0, 0, 0, 0}; if(LPS22HH_Reg_Write(I2Cx, LPS22HH_CTRL_REG1, buffer, 3)) return LPS22HH_ERROR; return LPS22HH_OK; } // LPS22HH_Error_Typedef LPS22HH_PRESS_OUT_Get(I2C_TypeDef *I2Cx, int32_t *P_OUT) { uint8_t buffer[3] = {0, 0, 0}; // read from standard registers if(LPS22HH_Reg_Read(I2Cx, LPS22HH_PRESS_OUT_XL, buffer, 3)) return LPS22HH_ERROR; *P_OUT = (buffer[2] << 16) | (buffer[1] << 8) | buffer[0]; return LPS22HH_OK; } // LPS22HH_Error_Typedef LPS22HH_TEMP_OUT_Get(I2C_TypeDef *I2Cx, int16_t *T_OUT) { uint8_t buffer[2] = {0, 0}; // read from normal registers if(LPS22HH_Reg_Read(I2Cx, LPS22HH_TEMP_OUT_L, buffer, 2)) return LPS22HH_ERROR; *T_OUT = (buffer[1] << 8) | buffer[0]; return LPS22HH_OK; } // LPS22HH_Error_Typedef LPS22HH_Pressure_Calculation(I2C_TypeDef *I2Cx, int32_t *value) { int32_t P_OUT = 0x00; if(LPS22HH_PRESS_OUT_Get(I2Cx, &P_OUT)) return LPS22HH_ERROR; *value = (P_OUT * 10) / 4096; printf("Get Pressure value : %d.%d hPa \n", *value / 10, abs(*value % 10)); return LPS22HH_OK; } // LPS22HH_Error_Typedef LPS22HH_Temperature_Calculation(I2C_TypeDef *I2Cx, int16_t *value) { int16_t T_OUT = 0x00; if(LPS22HH_TEMP_OUT_Get(I2Cx, &T_OUT)) return LPS22HH_ERROR; *value = T_OUT / 10; printf("Get Temperature value : %d.%d C \n", *value / 10, abs(*value % 10)); return LPS22HH_OK; } // LPS22HH_Error_Typedef LPS22HH_Calculation(I2C_TypeDef *I2Cx, int32_t *p_value, int16_t *t_value, bool oneshot) { if(oneshot){ uint8_t tmp = 0x00; if(LPS22HB_Reg_Read(I2Cx, LPS22HB_CTRL_REG2, &tmp, 1)) return LPS22HB_ERROR; tmp |= LPS22HB_CR2_ONE_SHOT; if(LPS22HB_Reg_Write(I2Cx, LPS22HB_CTRL_REG2, &tmp, 1)) return LPS22HB_ERROR; } u8 buffer = 0x00; if(LPS22HH_Reg_Read(I2Cx, LPS22HH_STATUS, &buffer, 1)) return LPS22HH_ERROR; if(buffer && LPS22HH_STATUS_P_DA != 0){ LPS22HH_Pressure_Calculation(I2Cx, p_value, fifo); LPS22HH_Altitude_Calculation(p_value); } if(buffer && LPS22HH_STATUS_T_DA != 0){ LPS22HH_Temperature_Calculation(I2Cx, t_value, fifo); } return LPS22HH_OK; } // void LPS22HH_Altitude_Calculation(int32_t *p_value) { float altitude = 44300 * (1 - pow(*p_value / 10132.5, 0.19)); printf("Get Altitude value : %.1f M \n", altitude); }
也可参考 ST 的 LPS22HH 使用代码STM32DUINO/LPS22HH
The End
看到一句话,感觉很棒:
社会太卷怎么办
读书,读书破万卷
P.S. 最近疫情严重,开始琢磨在家重蔬菜,生菜水培就是长得有点儿慢