当前位置: 首页 > news >正文

RA4M2开发IOT(10)----集成LPS22DF气压计

RA4M2开发IOT.10--集成LPS22DF气压计

  • 概述
  • 视频教学
  • 样品申请
  • 硬件准备
  • 参考程序
  • 产品特性
  • 通信模式
  • 速率
  • IIC属性配置
  • CS片选配置
  • SA0地址设置
  • 配置中断
  • 中断回调函数
  • 使能中断
  • 管脚初始化
  • 参考程序
  • LPS22DF初始化
  • 界面初始化
  • 中断回调函数
  • 气压数据显示

概述

本篇文章将延续现有 “动态显示 MEMS 数据” 的框架,在同一条 I²C 总线上新增 LPS22DF 数字气压计。
项目将具备 惯性 + 气压 的完整环境感知能力,并且借助涂鸦平台可快速把本地大气数据同步到云端,为室内气候监测、爬山/无人机高度预警等场景奠定基础。

最近在瑞萨RA的课程,需要样片的可以加qun申请:925643491。

视频教学

https://www.bilibili.com/video/BV1DjNmzyEuV

RA4M2开发IOT(10)----集成LPS22DF气压计

样品申请

https://www.wjx.top/vm/rCrkUrz.aspx

硬件准备

首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为R7FA4M2AD3CFL#AA0

在这里插入图片描述
同时添加RA4M2_IOT扩展版。

在这里插入图片描述

参考程序

https://github.com/CoreMaker-lab/RA4M2_IOT

https://gitee.com/CoreMaker/RA4M2_IOT

产品特性

LPS22DF是一款超紧凑型压阻绝对压力传感器,可用作数字输出气压计。LPS22DF相比前代产品具有更低的功耗和更小的压力噪声。

该器件包含传感元件和IC接口,该接口通过I²C、MIPI I3CSM或SPI接口实现传感元件与应用的通信,同时该器件也支持用于数据接口的广泛Vdd IO。检测绝对压力的传感元件由悬浮膜组成,采用ST开发的专门工艺进行制造。

LPS22DF采用全压塑孔LGA封装(HLGA)。可保证在-40 °C到+85 °C的温度范围都能工作。封装上有开孔,以便外部压力到达传感元件。

260-1260 hPa 的绝对压力范围,适用于多种气压应用。 最低电流消耗可达 1.7 μA,适合低功耗设备。 压力精度达 0.2 hPa,并具备 0.34 Pa 的低噪声和 0.45 Pa/°C 的温度补偿偏移。

通信模式

对于LPS22DF,可以使用IIC进行通讯。
最小系统图如下所示。

在这里插入图片描述

本文使用的板子原理图如下所示。

在这里插入图片描述

接入IOT板PCB如下所示。

在这里插入图片描述

在这里插入图片描述

速率

该模块支持的I2C速度为快速模式1M。

在这里插入图片描述

IIC属性配置

查看手册,可以得知LPS22DF的IIC地址为“1011100” 或者 “1011101”,即0x5C或0x5D。

在这里插入图片描述

CS片选配置

LPS22DF可以通过CS管脚进行IIC或者SPI通讯切换

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

SA0地址设置

通过设置SA0管脚的高低电平可以改变模块的地址。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

配置中断

这里的中断口对应P402。

在这里插入图片描述
在这里插入图片描述
在“New Stack”下选择Input > External IRQ (r_icu)。

在这里插入图片描述

模块配置如下所示。
● Name:g_external_irq4,这是该外部中断的名称。
● Channel:选择了4通道。
● Trigger:触发方式设置为Rising(上升沿触发),即信号上升时触发中断。
● Digital Filtering:未启用数字滤波(Not Supported)。
● Digital Filtering Sample Clock:由于数字滤波未启用,因此该项也未支持。
● Callback:指定了回调函数external_irq4_callback。当中断触发时,将调用此函数处理具体逻辑。
● Pin Interrupt Priority:设置为Priority 2,表示该中断的优先级为2。
● IRQ06:映射到引脚P402,即该中断信号通过引脚P000触发。

在这里插入图片描述

配置中断脚。

在这里插入图片描述

中断回调函数

● external_irq4_callback函数是外部中断的回调函数,当中断触发时,icu_irq_isr中断服务程序会调用此函数。
● lps22df_irq_flag变量在每次中断时赋值为1。

bool lps22df_irq_flag =0;
/* Called from icu_irq_isr */
void external_irq4_callback (external_irq_callback_args_t * p_args)
{(void) p_args;lps22df_irq_flag = 1;
}

在这里插入图片描述

使能中断

在app_peripheral_init添加开启中断和初始化。

    // 打开外部中断通道(用于接收 LPS22DF 的中断输出)fsp_err_t err = R_ICU_ExternalIrqOpen(&g_external_irq4_ctrl, &g_external_irq4_cfg);assert(FSP_SUCCESS == err);err = R_ICU_ExternalIrqEnable(&g_external_irq4_ctrl);assert(FSP_SUCCESS == err);

在这里插入图片描述

管脚初始化

使能SA0为低电平,配置模块地址。

在这里插入图片描述

在app_peripheral_init中添加LPS22DF的初始化。

    //LPS22DF CS->1R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_00, BSP_IO_LEVEL_HIGH);    //LPS22DF SA0->0R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_13, BSP_IO_LEVEL_LOW);   

在这里插入图片描述

参考程序

https://github.com/STMicroelectronics/lps22df-pid/

把对应驱动包导入到src文件夹。

在这里插入图片描述

添加头文件。

#include "lps22df_reg.h"

在这里插入图片描述

添加预设定义。

/* Extern variables ----------------------------------------------------------*//* Private functions ---------------------------------------------------------*/
/**   WARNING:*   Functions declare in this section are defined at the end of this file*   and are strictly related to the hardware platform used.**/
static int32_t platform_write_lps22df(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len);
static int32_t platform_read_lps22df(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len);
static void tx_com_lps22df( uint8_t *tx_buffer, uint16_t len );
static void platform_delay_lps22df(uint32_t ms);
static void platform_init_lps22df(void);
stmdev_ctx_t            dev_ctx_LPS22DF; // 设备上下文

在这里插入图片描述
在最下方添加LPS22DF的IIC读写函数。

/** @brief  Write generic device register (platform dependent)** @param  handle    customizable argument. In this examples is used in*                   order to select the correct sensor bus handler.* @param  reg       register to write* @param  bufp      pointer to data to write in register reg* @param  len       number of consecutive register to write**/
static int32_t platform_write_lps22df(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len)
{R_SCI_I2C_SlaveAddressSet(&g_i2c2_ctrl, 0x5C, I2C_MASTER_ADDR_MODE_7BIT);assert(FSP_SUCCESS == err);// 创建一个足够大的缓冲区来包含寄存器地址和数据uint8_t data[len + 1];data[0] = reg; // 将寄存器地址放在数据的开始memcpy(&data[1], bufp, len); // 复制数据到缓冲区err = R_SCI_I2C_Write(&g_i2c2_ctrl, data, len+1, true);assert(FSP_SUCCESS == err);/* Since there is nothing else to do, block until Callback triggers*///while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms)while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0){R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);timeout_ms--;}if (I2C_MASTER_EVENT_ABORTED == i2c_event){__BKPT(0);}/* Read data back from the I2C slave */i2c_event = I2C_MASTER_EVENT_ABORTED;timeout_ms           = 100000;return 0;
}/** @brief  Read generic device register (platform dependent)** @param  handle    customizable argument. In this examples is used in*                   order to select the correct sensor bus handler.* @param  reg       register to read* @param  bufp      pointer to buffer that store the data read* @param  len       number of consecutive register to read**/
static int32_t platform_read_lps22df(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len)
{R_SCI_I2C_SlaveAddressSet(&g_i2c2_ctrl, 0x5C, I2C_MASTER_ADDR_MODE_7BIT);assert(FSP_SUCCESS == err);err = R_SCI_I2C_Write(&g_i2c2_ctrl, &reg, 1, true);assert(FSP_SUCCESS == err);/* Since there is nothing else to do, block until Callback triggers*///while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms)while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms>0){R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);timeout_ms--;}if (I2C_MASTER_EVENT_ABORTED == i2c_event){__BKPT(0);}/* Read data back from the I2C slave */i2c_event = I2C_MASTER_EVENT_ABORTED;timeout_ms           = 100000;/* Read data from I2C slave */err = R_SCI_I2C_Read(&g_i2c2_ctrl, bufp, len, false);assert(FSP_SUCCESS == err);while ((I2C_MASTER_EVENT_RX_COMPLETE != i2c_event) && timeout_ms){R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);timeout_ms--;}if (I2C_MASTER_EVENT_ABORTED == i2c_event){__BKPT(0);}i2c_event = I2C_MASTER_EVENT_ABORTED;timeout_ms           = 100000;return 0;
}/** @brief  platform specific delay (platform dependent)** @param  ms        delay in ms**/
static void platform_delay_lps22df(uint32_t ms)
{R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS);
}

在这里插入图片描述

LPS22DF初始化

sensor_lps22df_init函数负责把 ST LPS22DF 气压/温度传感器接入到现有 I²C 总线,并配置为低噪声测量模式 。

/* ---------------------------------------------------------------------------* @brief  初始化 LPS22DF 数字气压计(气压 + 片内温度)*         - 共用 I²C 总线(SENSOR_BUS)*         - 配置为 10 Hz / 256 次平均 / ODR÷9 低通*         - 打开 DRDY 中断,MCU 可用外部中断捕获新数据* --------------------------------------------------------------------------*/
static void sensor_lps22df_init(void)
{/* 1. 局部缓冲/结构体 -------------------------------------------------- */lps22df_pin_int_route_t int_route;     // 中断路由寄存器镜像lps22df_bus_mode_t      bus_mode;      // 接口&滤波选项lps22df_id_t            id;            // WHO_AM_I 读取结果lps22df_md_t            md;            // 模式配置int                     ret;           // ST 驱动函数返回值/* 2. 绑定底层读/写/延时 ------------------------------------------------ */dev_ctx_LPS22DF.write_reg = platform_write_lps22df;  // I²C 写函数dev_ctx_LPS22DF.read_reg  = platform_read_lps22df;   // I²C 读函数dev_ctx_LPS22DF.mdelay    = platform_delay_lps22df;  // 毫秒延时dev_ctx_LPS22DF.handle    = &SENSOR_BUS;             // I²C 句柄/* 3. 读取并校验设备 ID ------------------------------------------------- */lps22df_id_get(&dev_ctx_LPS22DF, &id);printf("LPS22DF_ID=0x%x, whoamI=0x%x\r\n", LPS22DF_ID, id.whoami);if (id.whoami != LPS22DF_ID)   // 若连线或地址错误,停在此处while (1);/* 4. 先 Boot -> 再软复位 ------------------------------------------------ */ret = lps22df_init_set(&dev_ctx_LPS22DF, LPS22DF_BOOT);   if (ret) while (1);ret = lps22df_init_set(&dev_ctx_LPS22DF, LPS22DF_RESET);  if (ret) while (1);/* 5. 启用驱动推荐配置:BDU=1 / IF_INC=1 ------------------------------- */lps22df_init_set(&dev_ctx_LPS22DF, LPS22DF_DRV_RDY);/* 6. 选择接口 + 滤波模式 ---------------------------------------------- */bus_mode.filter    = LPS22DF_FILTER_AUTO;  // 写寄存器自动关 LPF,之后再恢复bus_mode.interface = LPS22DF_SEL_BY_HW;    // 由 SEL 脚决定 I²C / SPIlps22df_bus_mode_set(&dev_ctx_LPS22DF, &bus_mode);/* 7. 设置测量输出速率 & 滤波/平均参数 --------------------------------- */md.odr = LPS22DF_10Hz;            // ODR = 10 Hzmd.avg = LPS22DF_256_AVG;         // 256 次平均,降低噪声md.lpf = LPS22DF_LPF_ODR_DIV_9;   // 低通截止 ≈ 1.1 Hzlps22df_mode_set(&dev_ctx_LPS22DF, &md);/* 8. 使能气压/温度 DRDY 中断 ------------------------------------------- */lps22df_pin_int_route_get(&dev_ctx_LPS22DF, &int_route); // 读默认int_route.drdy_pres = PROPERTY_ENABLE;   // 数据就绪 → INT/DRDY 脚lps22df_pin_int_route_set(&dev_ctx_LPS22DF, &int_route);/* 现在 LPS22DF 已在 10 Hz 低噪声模式开始工作,可在主循环通过中断或轮询读取气压 (hPa) 与温度 (°C)。*/}

在这里插入图片描述
在主程序中添加初始化。

    // 初始化 LPS22DF 传感器,配置速率和模式sensor_lps22df_init();

在这里插入图片描述

界面初始化

在OLED_switch添加LPS22DF界面初始化。

static void OLED_switch(void)
{if (g_oled_clear)                     // ← 仅当需切屏时进入{g_oled_clear = 0;                 // 标记已完成清屏OLED_Clear();                     // ① 清显存并刷新,黑场一次switch (g_oled_page)              // ② 根据当前页写“标签”{/* ---------- Page-0 : Tuya 模组 ---------- */case 0:OLED_ShowString(0,  0, (u8 *)"TUYA",       16,1);OLED_ShowString(0, 16, (u8 *)"WIFI MODE:", 16,1);OLED_ShowString(0, 32, (u8 *)"AP MODE:",   16,1);break;/* ---------- Page-1 : LSM6DSV16X ---------- */case 1:OLED_ShowString(0,  0, (u8 *)"MEMS_LSM6DSV16X", 12,1);OLED_ShowString(0, 12, (u8 *)"TAP:",   12,1);OLED_ShowString(60,12, (u8 *)"TEMP:",  12,1);OLED_ShowString(0, 24, (u8 *)"X(mg):", 12,1);OLED_ShowString(0, 36, (u8 *)"Y(mg):", 12,1);OLED_ShowString(0, 48, (u8 *)"Z(mg):", 12,1);break;/* ---------- Page-2 : LPS22DF 气压计 ------- */case 2:OLED_ShowString(0,  0, (u8 *)"MEMS_LPS22DF", 16,1);OLED_ShowString(0, 16, (u8 *)"Pressure:", 16,1);OLED_ShowString(0, 32, (u8 *)"Temp:",   16,1);break;}OLED_Refresh();                   // ③ 推送骨架到屏幕}
}

在这里插入图片描述

中断回调函数

lps22df_read_data_drdy函数是气压计 LPS22DF 的 DRDY 中断读取函数。
由于没有不需要上报涂鸦,所以2中的wifi_Update和g_tuya_up_data注释掉了。
两个变量推送到 OLED 第 2 页或打包成 Tuya DP 上报云端。

/******************************************************************************* @brief  通过 DRDY 中断读取 LPS22DF 气压计数据*         - 由外部中断服务程序置位 lps22df_irq_flag*         - 进入后读取最新气压 / 温度(若数据已就绪)*         - 同时触发涂鸦 DP 上报计时器******************************************************************************/
double lps22df_data_pressure=0.0f;
double lps22df_data_temp=0.0f;
static void lps22df_read_data_drdy(void)
{/* -------- 1. 检测由 EXTI 产生的数据就绪标志 ------------------ */if (lps22df_irq_flag)                    // INT/DRDY 低电平到来{lps22df_irq_flag = false;            // 先清除本地标志/* -------- 2. 触发涂鸦数据上报计时 ----------------------- */
//        wifi_Update   = 1;                   // 下轮主循环立刻刷新 DP
//        g_tuya_up_data = 2000;               // 2 s 后再次上报 (计数器复位)/* -------- 3. 查询 LPS22DF 数据就绪标志 ------------------ */lps22df_all_sources_t all_src;lps22df_all_sources_get(&dev_ctx_LPS22DF, &all_src);/* -------- 4. 仅在有新数据时读取压强/温度 ---------------- */if (all_src.drdy_pres || all_src.drdy_temp){static lps22df_data_t data;      // 静态减少栈开销lps22df_data_get(&dev_ctx_LPS22DF, &data);lps22df_data_pressure = data.pressure.hpa;lps22df_data_temp = data.heat.deg_c;
//            printf("pressure [hPa]: %6.2f  temperature [degC]: %6.2f\r\n",
//                   data.pressure.hpa, data.heat.deg_c);/* 此处可再把 data 填入 OLED/Page-2 或涂鸦 DP */}}
}

在这里插入图片描述

之后在主程序中调用。

// 处理 LPS22DF事件,(例如气压,温度)lps22df_read_data_drdy();

在这里插入图片描述

气压数据显示

OLED_lps22df_MEMS() 是 OLED 第 2 页面(气压计页)的动态刷新函数。
● 通过 g_tuya_num 计数器,每 100 ms 刷新一次,既保证数据实时,又减轻 I²C 负担。
● 调用全局缓存 lps22df_data_pressure 与 lps22df_data_temp(由 DRDY 中断读取函数更新),把 气压 以 “xxxx.xx hPa”,温度 以 “±xxx.xx °C” 的格式显示在屏幕指定坐标。
● 采用分段写字符的方式(整数->小数点->小数),避免 sprintf 带来的堆栈及时间开销。
● 最后执行 OLED_Refresh() 将修改后的显存块写回驱动 IC,实现无闪烁、平滑的实时数据展示。

/* ------------ Page-2 : MEMS_lps22df -------------------------- */
static void OLED_lps22df_MEMS(void)
{/* ---------- 1. 节流判断:每 1 ms 主循环 +1,满 100 ≈ 100 ms ---------- */if(g_tuya_num<100)g_tuya_num++;else{g_tuya_num=0;uint32_t t100 = 0;// 小数两位 ×100 的临时变量OLED_ShowNum  (72, 16,(uint32_t)lps22df_data_pressure, 4, 16, 1);// 整数位/*   小数点 '.'       */OLED_ShowChar (104, 16, '.',16, 1);/*   小数部分:xx     */t100 = (uint32_t)(lps22df_data_pressure * 100);OLED_ShowNum  (112, 16,(uint32_t)t100%100, 2, 16, 1);/*   正负号 */if(lps22df_data_temp<0)OLED_ShowChar (72, 32, '-',16, 1);elseOLED_ShowChar (72, 32, '+',16, 1);OLED_ShowNum (80, 32,(uint32_t)fabs(lps22df_data_temp),3,16, 1);// 整数位/*   小数点 '.'       */OLED_ShowChar (104, 32, '.',16, 1);/*   小数部分:xx     */t100=(uint32_t)(fabs(lps22df_data_temp)*100);OLED_ShowNum (112, 32,(uint32_t)t100%100,2,16, 1);OLED_Refresh();}
}

在这里插入图片描述
在主程序中添加OLED界面显示。

        if(g_oled_page==0) /* Page-0 : Tuya 状态页 */OLED_DrawPage_TUYA();// 显示 Wi-Fi / AP 配网信息else if(g_oled_page==1)/* Page-1 : LSM6DSV16X 状态页 */OLED_DrawPage_MEMS();// 显示单/双击、温度、XYZ 加速度else if(g_oled_page==2)/* Page-2 : LPS22DF 状态页 */OLED_lps22df_MEMS();// 显示气压、温度

在这里插入图片描述

http://www.lryc.cn/news/573933.html

相关文章:

  • 扫雷中的数学原理
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月22日第116弹
  • 64-Oracle Redo Log
  • 肖臻《区块链技术与应用》第六讲:比特币网络
  • 点点(小红书AI搜索):生活场景的智能搜索助手
  • 数据库(1)-SQL
  • C++ - 标准库之 <string> npos(npos 概述、npos 的作用)
  • 2140、解决智力问题
  • 用 Python 绘制动态方块热力图:从数据到可视化的完美蜕变
  • Java基础复习之接口
  • PyTorch 入门学习笔记
  • LLM存储优化:大量长对话解决方案
  • 解决OSS存储桶未创建导致的XML错误
  • SQL Server基础语句4:数据定义
  • C#设计模式-Builder-生成器-对象创建型模式
  • JMeter API 并发性能测试计划JMX文件解析
  • 【力扣 中等 C】983. 最低票价
  • 通义大模型在文档自动化处理中的高效部署指南(OCR集成与批量处理优化)
  • Flink SourceFunction深度解析:数据输入的起点与奥秘
  • OpenAI 如何将 Kubernetes 扩展到了 7500 个节点
  • 46- 赎金信
  • 如何仅用AI开发完整的小程序<3>—创建小程序基础框架
  • python案例练习
  • 《单光子成像》第八章 预习2025.6.22
  • 零基础学习Redis(14) -- Spring中使用Redis
  • AIGC技术的本质:统计学驱动的智能革命
  • 制造业B端登录页案例:生产数据安全入口的权限分级设计
  • 【ELK(Elasticsearch+Logstash+Kibana) 从零搭建实战记录:日志采集与可视化】
  • 防御悬垂指针:C++的多维度安全实践指南
  • 【分布式技术】Bearer Token以及MAC Token深入理解