# sht30_2 **Repository Path**: lye21/sht30_2 ## Basic Information - **Project Name**: sht30_2 - **Description**: 新版的 sht30 无线温湿度传感器 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-06 - **Last Updated**: 2026-05-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 整体项目结构如下 1、通过I2C1读取 sht30 的数据 2、然后通过串口2,将数据发送至 lora 模块 3、lora 模块通过M1,M0 引脚控制模式,M1=1 M0=0 为休眠,M1=0 M0=0 为发送,M1=1 M0=1 为配置模式 4、整个项目需要考虑低功耗,stm32 发送完数据后,需要进入停止模式,lora 也进入休眠模式 5、每 30s 发送一次数据 6、stm32 第一次开机时,需要留 10 秒钟的窗口给 stlink 下载用,否则进入了休眠模式就下载不了了 7、有一个读取电池电压的电路,需要先将 BAT_EN 设置为高电平,通过ADC 通道 1 进行读取电池的电压,电压经过了1:3的分压 8、项目支持通过串口 1 修改设备编码,设备编码格式为 LTT+5 位数字,通过串口发送$LTT00100&,就将设备编码修改为 LTT00100,初始默认编码为 TESTDEV 9、lora 发送的数据格式为:<T00100,温度,湿度,电压# 10、串口 1 作为调试串口用,用于打印运行信息 11、开机时初始化 LoRa 模块,M1=M0=1 进入配置模式,通过串口2发送 0xC0 0x00 0x08 0xFF 0xFF 0x62 0x00 0x17 0x87 0x00 0x00,设置成功后模块返回相同数据 --- ## 当前开发状态 ### 已完成功能 | 功能 | 状态 | 说明 | |------|------|------| | SHT30 温湿度读取 | ✅ | I2C1 通信,CRC-8 校验,高精度单次测量模式 | | printf 调试输出 | ✅ | 重定向到 USART1,整数格式化避免 float printf | | ADC 电池电压 | ✅ | 50次轮询采样 + 中位值平均滤波,BAT_EN 控制,1:3 分压计算 | | LoRa 数据发送 | ✅ | M1=0 M0=0 透明传输,格式 &CODE,T,H,V# | | LoRa 休眠控制 | ✅ | M1=1 M0=0 休眠模式 | | LoRa 开机初始化 | ✅ | M1=1 M0=1 配置模式,发送11字节配置数据,校验返回 | | 设备编码修改 | ✅ | 串口1发送 $CODE& 格式,Flash 持久化存储 | | RTC 30秒唤醒 | ✅ | LSE 32.768kHz,CK_SPRE 时钟源 | | Stop 低功耗模式 | ✅ | 低功耗调压器 + WFI,外设反初始化 + GPIO 模拟模式 | | 10秒启动窗口 | ✅ | 循环延时 + 串口命令处理,支持 ST-Link 下载和设备编码修改 | ### 关键代码位置 - **主逻辑**: `Core/Src/main.c` — 全部在 USER CODE 区域 - **SHT30 驱动**: `Core/Src/sht30.c` + `Core/Inc/sht30.h` - **中断处理**: `Core/Src/stm32l0xx_it.c` — RTC_IRQHandler, USART1_IRQHandler - **GPIO 配置**: `Core/Src/gpio.c` — BAT_EN(PA0), M1(PA4), M0(PA5) ### 主程序流程 ``` 开机 ├─ HAL_Init / SystemClock_Config / 外设初始化 ├─ ADC 校准 ├─ 从 Flash 读取设备编码 ├─ 启用 USART1 中断接收 ├─ LoRa_Init() — M1=M0=1 配置模式,发送配置数据,校验返回 ├─ 打印启动信息 ├─ 10秒窗口(每10ms处理一次串口命令) ├─ Sensor_Send_Cycle() — 首次读取传感器并发送 ├─ RTC_Wakeup_Init() — 启动30秒唤醒定时器 └─ Enter_Stop_Mode() — 进入低功耗 while(1) 循环(RTC 唤醒后) ├─ SystemClock_Config() — 恢复 HSE 时钟 ├─ 重新初始化所有外设(GPIO/ADC/I2C/USART1/USART2) ├─ ADC 校准 ├─ Sensor_Send_Cycle() — 读取传感器并发送 ├─ RTC_Wakeup_Init() — 重启30秒唤醒定时器 ├─ HAL_SuspendTick() — 挂起 SysTick └─ Enter_Stop_Mode() — 再次进入低功耗 ``` ### 低功耗处理细节 **最终休眠功耗:10uA**(从初始 600uA 优化至此) #### ADC 电池电压采样 采用**50次轮询采样 + 中位值平均滤波**算法: 1. `BAT_EN = HIGH`,使能分压电路,延时 1ms 稳定 2. 连续 50 次 `HAL_ADC_Start` → `PollForConversion` → `GetValue` → `Stop` 3. `MedianAverageFilter()`:对 50 个采样值冒泡排序 → 去掉最小值和最大值 → 剩余 48 个取平均 4. `BAT_EN = LOW`,关闭分压电路 5. 电压计算:`filtered × 3300 × 3 / 4095`(12位ADC,3.3V参考,1:3分压) 中位值平均滤波能有效剔除偶发干扰(如开关噪声),比简单算术平均更稳定。 > **关于 DMA 方案的取舍:** 曾尝试 ADC DMA + 3通道(CH1/TEMPSENSOR/VREFINT)方式, > 但 TEMPSENSOR 和 VREFINT 内部模块在 Stop 模式下无法完全关闭, > 导致休眠功耗从 10uA 升至 20-30uA。最终放弃 DMA,保留轮询方式。 #### 600uA → 10uA 优化过程 **初始问题:** 开机进入 Stop 模式后功耗 600uA,远超预期。 **排查与解决:** 1. **LoRa 休眠模式错误(最大原因)** - 问题:最初代码将 LoRa 休眠设为 M1=1, M0=1,这是配置模式而非休眠模式 - LoRa 在配置模式下持续消耗电流(约 300-500uA) - 修正:改为 M1=1, M0=0,这才是 E220 模块的正确休眠模式 - 影响:此一项就减少了约 300-500uA 2. **外设未完整反初始化** - 问题:最初只关闭了外设时钟,没有调用 HAL_DeInit,外设内部寄存器仍保持活跃状态 - 修正:进入 Stop 前依次调用 HAL_ADC_DeInit、HAL_UART_DeInit(&huart1/&huart2)、HAL_I2C_DeInit(&hi2c1) - 影响:减少约 50-100uA 3. **GPIO 引脚浮空漏电** - 问题:UART/I2C/ADC 引脚在 Stop 模式下仍保持复用功能模式,内部上拉/下拉产生漏电 - 修正:将 PA9/PA10(USART1)、PA2/PA3(USART2)、PB6/PB7(I2C1)、PA1(ADC) 全部设为 GPIO_MODE_ANALOG + GPIO_NOPULL - 模拟模式是 GPIO 的最低功耗状态,关闭了输入施密特触发器和输出驱动器 - 影响:减少约 20-50uA 4. **控制引脚电平未锁定** - 问题:进入 Stop 后未显式确认 BAT_EN=低、M1=高、M0=低,可能因时序问题导致短暂漏电 - 修正:在 Enter_Stop_Mode() 中显式写入 BAT_EN=RESET、M1=SET、M0=RESET - 输出推挽模式在 Stop 下保持电平,确保 LoRa 休眠和分压电路关闭 5. **未使用 GPIO 时钟关闭** - 修正:关闭 GPIOC 和 GPIOH 时钟(本项目未使用这两个端口的外设) 6. **USART1 中断接收未停止** - 问题:HAL_UART_Receive_IT 在 Stop 前仍活跃,可能导致异常唤醒 - 修正:调用 HAL_UART_AbortReceive(&huart1) 停止中断接收 #### Enter_Stop_Mode() 完整步骤 ``` 1. LoRa_SetSleep() — M1=1, M0=0,LoRa 进入休眠 2. HAL_UART_AbortReceive() — 停止 USART1 中断接收 3. HAL_ADC_DeInit() — 反初始化 ADC 4. HAL_UART_DeInit() ×2 — 反初始化 USART1、USART2 5. HAL_I2C_DeInit() — 反初始化 I2C1 6. BAT_EN = LOW — 关闭电池分压电路 7. M1 = HIGH, M0 = LOW — 锁定 LoRa 休眠电平 8. PA9/PA10 → Analog — USART1 引脚最低功耗 9. PA2/PA3 → Analog — USART2 引脚最低功耗 10. PB6/PB7 → Analog — I2C1 引脚最低功耗 11. PA1 → Analog — ADC 引脚最低功耗 12. 关闭 USART1/2/I2C1/ADC1 时钟 13. 关闭 GPIOC/GPIOH 时钟 14. HAL_SuspendTick() — 挂起 SysTick,避免周期性中断 15. 清除 RTC 唤醒标志 16. HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI) ``` #### 唤醒后恢复步骤 ``` 1. SystemClock_Config() — 恢复 HSE 4MHz 时钟 2. HAL_ResumeTick() — 恢复 SysTick 3. 使能 GPIOA/B/C/H 时钟 4. MX_GPIO_Init() — 重新初始化 GPIO 5. MX_ADC_Init() — 重新初始化 ADC 6. MX_USART1_UART_Init() — 重新初始化 USART1 7. MX_USART2_UART_Init() — 重新初始化 USART2 8. MX_I2C1_Init() — 重新初始化 I2C1 9. ADC 校准 10. USART1 中断接收重启 ``` #### 硬件功耗构成(10uA 总功耗) | 来源 | 估算电流 | 说明 | |------|----------|------| | STM32L051 Stop 模式 | ~0.4-1uA | 低功耗调压器 + WFI | | HT7550 (5V LDO) | ~120uA | 电池→5V,静态电流 | | SSP7603 (3.3V LDO) | ~50uA | 5V→3.3V,静态电流 | | E220 LoRa 休眠 | ~5-10uA | M1=1 M0=0 休眠模式 | | SHT30 待机 | ~0.5-2uA | I2C 总线上 | | 其他(DW07D、TP4056等) | ~5-10uA | 电池保护、充电IC | 注:LDO 静态电流是从电池端测量,MCU 侧测量为 10uA ### 待优化项 | 问题 | 状态 | 说明 | |------|------|------| | 待机功耗 600uA → 10uA | ✅ 已解决 | 详见低功耗处理细节章节 | | 烧录问题 | ⚠️ 注意 | Stop 模式下 SWD 失效,需按住 Reset 连接 ST-Link | ### EIDE 项目配置 | 参数 | 值 | 说明 | |------|------|------| | 项目名 | sht30_2 | EIDE 工程名称 | | 芯片类型 | ARM Cortex-M0+ | STM32L051C8T6 | | 工具链 | GCC (arm-none-eabi) | 版本 5 | | Pack | Keil/STM32L0xx_DFP.2.1.0 | 设备支持包 | | 源码目录 | ../../sht32_2 | 指向 CubeMX 生成的源码 | | 预处理宏 | STM32L051xx, USE_HAL_DRIVER | HAL 驱动宏 | | 头文件路径 | Core/Inc, Drivers/... | 同 CubeMX Makefile | | 链接脚本 | STM32L051XX_FLASH.ld | 自定义 scatter file | | 输出格式 | ELF | 不生成 bin(通过 objcopy 手动转换) | | 烧录器 | OpenOCD (stlink) | interface=stlink, target=stm32l0 | | 烧录基地址 | 0x08000000 | Flash 起始地址 | | C 标准 | c11 | 编译器语言标准 | | 优化级别 | -Og | 调试级优化 | | float-abi | hard | 浮点 ABI | | newlib-nano | 启用 | 减小代码体积 | | one-elf-section-per-function | 启用 | 链接时垃圾回收 | | Heap/Stack | 0x200 / 0x400 | 链接脚本定义 | ### CubeMX 配置参数 | 参数 | 值 | 说明 | |------|------|------| | MCU | STM32L051C8Tx | LQFP48 封装 | | CubeMX 版本 | 6.17.0 | | | 固件包 | STM32Cube FW_L0 V1.12.4 | | | 目标工具链 | Makefile | GCC | | SYSCLK | HSE 4MHz | 外部晶振 | | AHB 分频 | /2 → 2MHz | | | APB1/APB2 | /1 → 2MHz | | | RTC 时钟 | LSE 32.768kHz | 外部低速晶振 | | ADC | CH1 单通道,连续转换,160.5周期采样 | 无 DMA | | I2C1 | Timing=0x00000508 | 标准模式 | | USART1 | 9600 baud, Asynchronous | 调试串口 | | USART2 | 9600 baud, Asynchronous | LoRa 串口 | | Heap | 0x200 | | | Stack | 0x400 | | | Flash | 64KB (0x08000000) | | | RAM | 8KB (0x20000000) | | ### 引脚定义 | 引脚 | 功能 | 说明 | |------|------|------| | PA0 | BAT_EN | 电池分压使能,高电平有效 | | PA1 | BAT_ADC | ADC 通道1,电池电压采样 | | PA2 | USART2_TX | LoRa 模块 TX | | PA3 | USART2_RX | LoRa 模块 RX | | PA4 | M1 | LoRa 模式控制 M1 | | PA5 | M0 | LoRa 模式控制 M0 | | PA9 | USART1_TX | 调试串口 TX | | PA10 | USART1_RX | 调试串口 RX | | PB6 | I2C1_SCL | SHT30 时钟线 | | PB7 | I2C1_SDA | SHT30 数据线 | ### Flash 存储布局 - 地址: `0x0800FF80`(最后一页,page 511,128字节/页) - 布局: `[4B magic 0xA5A5A5A5][8B 设备编码][...空闲...]` - 默认编码: `TESTDEV`