基于STM32温湿度检测设计

一、系统概述与核心功能

1. 系统定位

基于STM32的温湿度检测系统以“环境感知-数据处理-多端交互-低功耗续航”为核心,通过高精度温湿度传感器实时采集环境参数,结合本地显示、数据存储与远程通信,实现室内外环境的智能化监测,适用于智能家居、农业大棚、工业仓储、实验室等场景,替代传统指针式温湿度计,提供数字化、网络化监测方案。

2. 核心功能模块

模块 功能描述
环境感知 高精度温湿度传感器(如SHT30/SHT31)采集数据,支持温度(-40125℃)、湿度(0100%RH)测量
数据处理 原始数据滤波(滑动平均/卡尔曼滤波)、单位转换(℃/%RH)、阈值判断(超限报警)
本地显示 OLED/LCD显示实时温湿度、历史曲线(可选)、报警状态、电池电量(便携版)
数据存储 存储历史数据(EEPROM/SD卡),支持按时间查询(如最近24小时极值)
远程通信 通过Wi-Fi(ESP8266)/蓝牙(HC-05)上传数据至手机APP/云端(如OneNET)
低功耗设计 待机时STM32进入STOP模式,传感器间歇工作(如每分钟采集1次),续航≥6个月(电池版)

二、硬件设计方案

1. 核心硬件选型

模块 型号 关键参数 接口方式
主控MCU STM32F103C8T6 72MHz Cortex-M3,64KB Flash,20KB RAM,I2C、SPI、UART,支持低功耗模式 核心控制器
温湿度传感器 SHT30(首选)/DHT22 SHT30:I2C接口,±0.3℃/±2%RH,16位分辨率;DHT22:单总线,±0.5℃/±2%RH I2C(PB6=SCL,PB7=SDA)/单总线(PA0)
显示模块 OLED 12864(I2C) 0.96寸,128×64像素,自发光,低功耗(<10mA),支持图形/字符显示 I2C(复用传感器总线)
存储模块 AT24C256(EEPROM) 256Kb(32KB),I2C接口,擦写10万次,存储约1万条温湿度记录(每条4字节) I2C(复用)
通信模块 ESP8266-12F(Wi-Fi) 802.11 b/g/n,UART接口,支持AT指令/透传模式,上传数据至云端 UART1(PA9=TX,PA10=RX)
报警模块 有源蜂鸣器+LED 蜂鸣器(5V,85dB),LED(红/绿双色),超限时声光报警 GPIO(PB0=蜂鸣器,PB1=LED)
电源模块 5V USB/3.7V锂电池+TP4056 主电源5V(USB),备用锂电池(3.7V/2000mAh),TP4056充电管理,AMS1117-3.3V稳压 双电源供电(自动切换)

2. 硬件电路设计要点

2.1 核心电路连接(以SHT30为例)

2.2 抗干扰与安全设计

三、软件设计与核心代码

1. 系统架构(FreeRTOS多任务调度)

采用FreeRTOS实时操作系统,划分5个核心任务(优先级从高到低):

  1. 传感器采集任务(优先级4):通过I2C读取SHT30数据,滤波后发送至消息队列。
  2. 数据处理任务(优先级3):解析温湿度数据,判断阈值,生成报警信号。
  3. 显示更新任务(优先级2):读取最新数据,更新OLED显示(实时值+历史曲线)。
  4. 存储任务(优先级2):将历史数据写入AT24C256/SD卡(按时间戳存储)。
  5. 通信任务(优先级1):通过ESP8266上传数据至云端(MQTT协议)。

2. 核心代码实现(基于HAL库)

2.1 SHT30传感器驱动(I2C通信)

#include "sht30.h"
#include "i2c.h"

// SHT30命令集(I2C)
#define SHT30_MEAS_HIGHREP 0x2400  // 高重复精度测量(15ms)
#define SHT30_READ_STATUS  0xF32D  // 读取状态寄存器
#define SHT30_SOFT_RESET   0x30A2  // 软复位

// 发送命令至SHT30
void SHT30_SendCmd(uint16_t cmd) {
  uint8_t buf[2] = {cmd>>8, cmd&0xFF};
  HAL_I2C_Master_Transmit(&hi2c1, 0x44<<1, buf, 2, 100);  // 地址0x44(写)
}

// 读取温湿度数据(返回0=成功,1=失败)
uint8_t SHT30_ReadData(float *temp, float *humi) {
  uint8_t buf[6];
  SHT30_SendCmd(SHT30_MEAS_HIGHREP);  // 启动高重复精度测量
  HAL_Delay(15);  // 等待测量完成
  HAL_I2C_Master_Receive(&hi2c1, 0x44<<1, buf, 6, 100);  // 读取6字节数据
  
  // 校验CRC(略,SHT30数据含CRC8校验,需验证)
  uint16_t raw_temp = (buf[0]<<8) | buf[1];
  uint16_t raw_humi = (buf[3]<<8) | buf[4];
  
  // 转换为物理量(公式参考SHT30 datasheet)
  *temp = -45 + 175 * (raw_temp / 65535.0f);  // 温度(℃)
  *humi = 100 * (raw_humi / 65535.0f);        // 湿度(%RH)
  return 0;
}

2.2 数据滤波与阈值判断

// 滑动平均滤波(窗口大小5)
#define FILTER_WINDOW 5
float temp_buffer[FILTER_WINDOW] = {0};
float humi_buffer[FILTER_WINDOW] = {0};
uint8_t filter_index = 0;

// 滤波后读取温湿度
void Get_FilteredData(float *temp, float *humi) {
  float raw_temp, raw_humi;
  SHT30_ReadData(&raw_temp, &raw_humi);  // 原始数据
  
  // 更新缓冲区
  temp_buffer[filter_index] = raw_temp;
  humi_buffer[filter_index] = raw_humi;
  filter_index = (filter_index + 1) % FILTER_WINDOW;
  
  // 计算平均值
  *temp = 0; *humi = 0;
  for (uint8_t i=0; i<FILTER_WINDOW; i++) {
    *temp += temp_buffer[i];
    *humi += humi_buffer[i];
  }
  *temp /= FILTER_WINDOW;
  *humi /= FILTER_WINDOW;
}

// 阈值判断(温度20-30℃,湿度40-60%RH为正常范围)
uint8_t Check_Threshold(float temp, float humi) {
  if (temp < 20 || temp > 30 || humi < 40 || humi > 60) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);  // 蜂鸣器报警
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);  // 红灯亮
    return 1;  // 超限
  } else {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    return 0;  // 正常
  }
}

2.3 OLED显示驱动(实时数据+历史曲线)

#include "oled.h"
#include "font.h"  // 字库(6x8/8x16 ASCII)

// 显示实时温湿度
void OLED_ShowTempHumi(float temp, float humi) {
  char str[20];
  sprintf(str, "Temp: %.1f C", temp);
  OLED_ShowString(0, 0, str, 16);  // 第0行
  sprintf(str, "Humi: %.1f %%", humi);
  OLED_ShowString(0, 2, str, 16);  // 第2行
}

// 显示历史曲线(简化版,仅画温度曲线)
void OLED_ShowHistory(float *temp_history, uint8_t len) {
  OLED_ClearArea(0, 4, 128, 32);  // 清屏第4-7行(32像素高)
  for (uint8_t i=0; i<len-1; i++) {
    uint8_t x1 = i*128/(len-1);
    uint8_t y1 = 32 - (uint8_t)(temp_history[i] - 15);  // 温度范围15-35℃映射到0-32像素
    uint8_t x2 = (i+1)*128/(len-1);
    uint8_t y2 = 32 - (uint8_t)(temp_history[i+1] - 15);
    OLED_DrawLine(x1, y1, x2, y2, 1);  // 画直线
  }
}

2.4 主程序框架(FreeRTOS任务调度)

#include "stm32f1xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "sht30.h"
#include "oled.h"
#include "at24c256.h"
#include "esp8266.h"

// 全局变量
float current_temp, current_humi;
float temp_history[60];  // 存储最近60分钟温度(每分钟1条)

int main(void) {
  HAL_Init();
  SystemClock_Config();  // 72MHz
  MX_I2C1_Init();        // I2C1(SHT30/OLED/AT24C256)
  MX_USART1_Init();      // UART1(ESP8266)
  OLED_Init();           // OLED初始化
  SHT30_Init();          // 传感器初始化(软复位)
  AT24C256_Init();       // EEPROM初始化
  ESP8266_Init();        // Wi-Fi模块初始化(连接路由器)
  
  // FreeRTOS任务创建
  xTaskCreate(Sensor_Task, "Sensor", 256, NULL, 4, NULL);    // 传感器采集
  xTaskCreate(DataProcess_Task, "Process", 256, NULL, 3, NULL);  // 数据处理
  xTaskCreate(Display_Task, "Display", 256, NULL, 2, NULL);    // 显示更新
  xTaskCreate(Storage_Task, "Storage", 256, NULL, 2, NULL);    // 数据存储
  xTaskCreate(Comm_Task, "Comm", 256, NULL, 1, NULL);        // 通信上传
  
  vTaskStartScheduler();  // 启动调度器
  while (1);
}

参考代码 基于STM32温湿度检测设计 www.youwenfan.com/contentcst/133687.html

四、关键技术与优化

1. 传感器精度提升

2. 低功耗设计

3. 数据可靠性

五、系统调试与扩展

1. 调试步骤

阶段 操作 工具
硬件调试 测量I2C信号(SCL/SDA)、传感器供电(3.3V) 示波器、万用表
传感器测试 用串口打印原始数据,对比标准温湿度计 串口助手、标准仪表
显示测试 显示固定字符串/曲线,检查OLED是否缺画 肉眼观察、逻辑分析仪(I2C波形)
通信测试 用AT指令测试ESP8266联网,上传数据至云端 网络调试助手、OneNET控制台

2. 扩展功能

专注于matlab/simulink,电子电路,编程