news 2026/4/21 15:20:21

手把手教你用零知IDE和STM32F103RBT6驱动SHT40传感器,做个带TFT屏的温湿度计(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用零知IDE和STM32F103RBT6驱动SHT40传感器,做个带TFT屏的温湿度计(附完整代码)

从零打造高精度温湿度监测仪:STM32与SHT40的完美结合

在智能家居和工业物联网快速发展的今天,环境监测已成为许多项目的基础需求。无论是温室大棚的精准农业,还是实验室的环境控制,一个稳定可靠的温湿度监测系统都至关重要。本文将带你从零开始,使用STM32F103RBT6微控制器和SHT40高精度传感器,配合TFT显示屏,打造一个功能完善、显示直观的温湿度监测设备。

1. 硬件准备与连接

1.1 所需材料清单

构建这个项目需要以下核心组件:

  • 主控芯片:STM32F103RBT6开发板(兼容零知标准板)
  • 传感器模块:SHT40温湿度传感器(精度±0.2℃/±2%RH)
  • 显示模块:240×240像素ST7789驱动TFT屏幕
  • 其他配件
    • 轻触开关(用于界面切换)
    • 4pin卧贴插座(连接传感器)
    • 杜邦线若干
    • 面包板或PCB(可选)

提示:SHT40传感器有多个版本,建议选择带电平转换的模块,避免3.3V与5V系统间的兼容问题。

1.2 电路连接详解

正确的硬件连接是项目成功的第一步。以下是详细的引脚对应关系:

STM32引脚连接器件功能说明备注
PA5SHT40 SCL软件I2C时钟线可自定义其他IO
PA4SHT40 SDA软件I2C数据线需上拉4.7k电阻
PB10TFT_CS屏幕片选信号SPI片选
PB11TFT_DC数据/命令选择
PB12TFT_RST屏幕复位信号可接MCU复位
PB13TFT_SCKSPI时钟线硬件SPI时钟
PB15TFT_MOSISPI数据输出硬件SPI数据线
PA0按键输入界面切换控制内部上拉,接地触发
3.3V传感器电源为SHT40和TFT供电确保电源稳定
GND共地连接所有器件的地线连接避免地环路干扰

接线注意事项

  1. I2C总线需要上拉电阻(通常4.7kΩ)
  2. TFT屏幕的背光可能需要单独供电
  3. 长距离连接时考虑使用屏蔽线减少干扰

2. 开发环境搭建

2.1 零知IDE基础配置

零知IDE为STM32开发提供了便捷的环境:

  1. 下载并安装最新版零知IDE(官网提供Windows/macOS版本)
  2. 安装STM32支持包:
    # 在零知IDE的包管理器中搜索并安装 STM32F1xx_DFP - STM32F1系列设备支持包
  3. 配置板卡选项:
    • 选择开发板类型:STM32F103RBT6
    • 设置调试接口:SWD
    • 配置时钟源:8MHz外部晶振

2.2 必要库的安装

本项目需要以下关键库支持:

  • 传感器驱动:Adafruit_SHT4x_Library
  • 显示驱动:Adafruit_ST7789
  • 图形库:Adafruit_GFX
  • 软件I2C:SoftWire

安装方法:

// 在零知IDE的库管理器中搜索并安装: 1. 搜索"SHT4x" → 安装Adafruit_SHT4x 2. 搜索"ST7789" → 安装Adafruit_ST7789 3. 搜索"SoftWire" → 安装Software I2C库

2.3 项目基础配置

创建新项目后,需要进行以下关键配置:

  1. 启用硬件SPI:
    • hal_conf.h中取消注释#define HAL_SPI_MODULE_ENABLED
  2. 设置优化级别:
    • 项目属性 → C/C++构建 → 设置优化为-O2
  3. 配置串口调试:
    • 启用USART1,波特率115200

3. 核心代码实现

3.1 传感器驱动实现

SHT40通过软件I2C通信,以下是关键代码段:

// 软件I2C配置 #define SCL_PIN PA5 #define SDA_PIN PA4 SoftWire sht40Wire(SCL_PIN, SDA_PIN); // 初始化传感器 bool initSHT40() { sht40Wire.begin(); sht40Wire.setClock(100000); // 100kHz I2C速度 // 发送复位命令 sht40Wire.beginTransmission(0x44); sht40Wire.write(0x94); // 复位命令 if(sht40Wire.endTransmission() != 0) { return false; } delay(10); return true; } // 读取温湿度数据 SHT40_Data readSHT40() { SHT40_Data data = {0, 0, false}; // 发送高精度测量命令 sht40Wire.beginTransmission(0x44); sht40Wire.write(0xFD); if(sht40Wire.endTransmission() != 0) { data.success = false; return data; } delay(10); // 等待测量完成 // 读取6字节数据 uint8_t bytes[6]; uint8_t count = sht40Wire.requestFrom(0x44, 6); if(count != 6) { data.success = false; return data; } for(int i=0; i<6; i++) { bytes[i] = sht40Wire.read(); } // CRC校验 if(crc8(bytes, 2) != bytes[2] || crc8(&bytes[3], 2) != bytes[5]) { data.success = false; return data; } // 数据转换 uint16_t tempRaw = (bytes[0] << 8) | bytes[1]; uint16_t humiRaw = (bytes[3] << 8) | bytes[4]; data.temperature = -45 + 175 * (float)tempRaw / 65535; data.humidity = -6 + 125 * (float)humiRaw / 65535; data.humidity = constrain(data.humidity, 0, 100); data.success = true; return data; }

3.2 TFT显示驱动

ST7789显示屏的初始化与基本绘图功能:

// 显示屏引脚定义 #define TFT_CS PB10 #define TFT_DC PB11 #define TFT_RST PB12 Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); // 初始化显示屏 void initTFT() { tft.init(240, 240); tft.setRotation(1); // 根据实际安装方向调整 tft.fillScreen(ST77XX_BLACK); // 设置默认字体 tft.setTextColor(ST77XX_WHITE); tft.setTextSize(1); } // 绘制温度环形图 void drawTempGauge(float temp) { int centerX = 120, centerY = 120; int radius = 80, thickness = 15; // 绘制背景 tft.drawCircle(centerX, centerY, radius, ST77XX_DARKGREY); // 计算填充角度 (0-50℃范围) float percent = constrain(temp, 0, 50) / 50.0; int endAngle = 360 * percent; // 绘制温度弧线 for(int i=0; i<=endAngle; i++) { float angle = radians(i-90); // 从顶部开始 int x = centerX + radius * cos(angle); int y = centerY + radius * sin(angle); tft.drawLine(centerX, centerY, x, y, ST77XX_CYAN); } // 显示温度值 tft.setCursor(centerX-30, centerY-10); tft.setTextSize(2); tft.print(temp, 1); tft.print("℃"); }

3.3 主程序逻辑

整合传感器读取与显示更新的主循环:

// 全局变量 SHT40_Data sensorData; unsigned long lastUpdate = 0; const unsigned long UPDATE_INTERVAL = 1000; // 1秒更新一次 uint8_t currentScreen = 0; // 0-温度, 1-湿度, 2-VPD, 3-信息 void setup() { Serial.begin(115200); initTFT(); if(!initSHT40()) { Serial.println("SHT40初始化失败!"); while(1); } // 配置按键中断 pinMode(PA0, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PA0), switchScreen, FALLING); // 显示初始界面 updateDisplay(); } void loop() { unsigned long currentMillis = millis(); // 定时读取传感器 if(currentMillis - lastUpdate >= UPDATE_INTERVAL) { sensorData = readSHT40(); if(sensorData.success) { updateDisplay(); } lastUpdate = currentMillis; } } // 更新显示内容 void updateDisplay() { tft.fillScreen(ST77XX_BLACK); switch(currentScreen) { case 0: // 温度界面 drawTempGauge(sensorData.temperature); break; case 1: // 湿度界面 drawHumiGauge(sensorData.humidity); break; case 2: // VPD界面 drawVPDScreen(calculateVPD(sensorData)); break; case 3: // 信息界面 drawInfoScreen(sensorData); break; } } // 按键中断服务函数 void switchScreen() { static unsigned long lastPress = 0; if(millis() - lastPress > 300) { // 防抖 currentScreen = (currentScreen + 1) % 4; updateDisplay(); lastPress = millis(); } }

4. 高级功能实现

4.1 VPD(蒸气压差)计算

VPD是评估植物生长环境的重要指标:

float calculateVPD(SHT40_Data data) { if(!data.success) return -1; // 计算饱和蒸气压(SVP) float svp = 0.6108 * exp(17.27 * data.temperature / (data.temperature + 237.3)); // 计算实际蒸气压(AVP) float avp = data.humidity / 100.0 * svp; // 返回蒸气压差(kPa) return svp - avp; } // VPD评估函数 const char* evaluateVPD(float vpd) { if(vpd < 0.8) return "湿度过高(霉变风险)"; else if(vpd > 1.2) return "湿度过低(植物胁迫)"; else return "适宜范围"; }

4.2 多界面切换设计

实现四个信息展示界面的平滑切换:

  1. 温度界面:环形温度计+数字显示
  2. 湿度界面:环形湿度计+百分比显示
  3. VPD界面:仪表盘+环境评估
  4. 信息界面:传感器参数+系统状态
// 绘制湿度界面 void drawHumiGauge(float humidity) { int centerX = 120, centerY = 120; int radius = 80; // 绘制背景 tft.drawCircle(centerX, centerY, radius, ST77XX_DARKGREY); // 计算填充角度 float percent = constrain(humidity, 0, 100) / 100.0; int endAngle = 360 * percent; // 绘制湿度弧线 for(int i=0; i<=endAngle; i++) { float angle = radians(i-90); int x = centerX + radius * cos(angle); int y = centerY + radius * sin(angle); tft.drawLine(centerX, centerY, x, y, ST77XX_BLUE); } // 显示湿度值 tft.setCursor(centerX-30, centerY-10); tft.setTextSize(2); tft.print(humidity, 1); tft.print("%"); // 显示界面标识 tft.setTextSize(1); tft.setCursor(10, 220); tft.print("湿度监测 | 按按键切换"); }

4.3 数据平滑处理

为减少传感器噪声,实现数据平滑算法:

#define SAMPLE_SIZE 5 float tempHistory[SAMPLE_SIZE]; uint8_t historyIndex = 0; // 移动平均滤波 float smoothTemperature(float newTemp) { tempHistory[historyIndex] = newTemp; historyIndex = (historyIndex + 1) % SAMPLE_SIZE; float sum = 0; for(int i=0; i<SAMPLE_SIZE; i++) { sum += tempHistory[i]; } return sum / SAMPLE_SIZE; }

5. 项目优化与调试

5.1 常见问题排查

问题1:传感器无响应或读数错误

解决方案

  1. 检查I2C线路连接是否正确
  2. 确认电源电压稳定(3.3V±10%)
  3. 降低I2C时钟速度测试
  4. 添加I2C上拉电阻(4.7kΩ)

问题2:TFT显示异常

解决方案

  1. 确认SPI引脚配置正确
  2. 检查屏幕背光供电
  3. 调整屏幕初始化延迟
  4. 尝试降低SPI时钟速度

问题3:按键响应不稳定

解决方案

  1. 添加硬件消抖电路(0.1μF电容)
  2. 调整软件防抖时间
  3. 检查上拉电阻是否有效

5.2 性能优化技巧

  1. SPI优化

    • 启用DMA传输
    • 使用双缓冲机制
    // 示例:SPI DMA配置 SPI_DMA_Init(); SPI_DMA_Enable();
  2. 电源管理

    • 添加LC滤波电路
    • 使用低噪声LDO稳压器
    • 在代码中实现睡眠模式
  3. 内存优化

    • 将大字体数据放入Flash
    • 使用内存池管理动态分配
    // 将字体数据存入Flash const uint8_t fontData[] PROGMEM = {...};

5.3 扩展功能建议

  1. 数据记录

    • 添加SD卡模块存储历史数据
    • 实现CSV格式数据导出
  2. 无线传输

    • 集成ESP8266实现WiFi上传
    • 使用蓝牙模块进行手机连接
  3. 报警功能

    • 设置温湿度阈值报警
    • 添加蜂鸣器和LED指示灯
  4. 云端监控

    • 对接MQTT服务器
    • 开发Web监控界面
// 简单的阈值报警实现 void checkAlarm(SHT40_Data data) { static bool tempAlarm = false; static bool humiAlarm = false; if(data.temperature > 30.0 && !tempAlarm) { triggerAlarm("高温警告!"); tempAlarm = true; } else if(data.temperature <= 30.0) { tempAlarm = false; } if(data.humidity > 80.0 && !humiAlarm) { triggerAlarm("高湿警告!"); humiAlarm = true; } else if(data.humidity <= 80.0) { humiAlarm = false; } }

6. 项目进阶与变种

6.1 外壳设计与安装

一个专业的项目离不开精良的外壳设计:

  1. 3D打印方案

    • 使用PLA材料打印定制外壳
    • 设计散热孔和安装支架
    • 考虑防水需求时可使用PETG材料
  2. PCB设计

    • 将电路集成到单一PCB
    • 添加电源管理电路
    • 设计标准的传感器接口
  3. 安装建议

    • 避免阳光直射影响温度测量
    • 保持传感器周围空气流通
    • 远离热源和潮湿区域

6.2 多传感器融合

提升系统功能性的几种扩展方案:

  1. CO2传感器:SCD30或MH-Z19
  2. 气压传感器:BMP280
  3. 光照传感器:BH1750
  4. 空气质量传感器:SGP30
// 多传感器数据融合示例 typedef struct { float temperature; float humidity; float co2; float pressure; float lux; } EnvironmentData; EnvironmentData readAllSensors() { EnvironmentData data; // 读取各传感器 data.temperature = readSHT40().temperature; data.humidity = readSHT40().humidity; data.co2 = readSCD30().co2; data.pressure = readBMP280().pressure; data.lux = readBH1750().lux; return data; }

6.3 低功耗优化

对于电池供电的应用场景:

  1. 硬件优化

    • 选择低功耗版本STM32
    • 使用高效率DC-DC转换器
    • 添加电源开关电路
  2. 软件优化

    • 实现深度睡眠模式
    • 降低采样频率
    • 优化显示刷新策略
// 低功耗模式实现 void enterSleepMode() { // 关闭外设 SPI.end(); sht40Wire.end(); // 配置唤醒源 attachInterrupt(digitalPinToInterrupt(PA0), wakeUp, LOW); // 进入停止模式 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 唤醒后重新初始化 SystemClock_Config(); initPeripherals(); } void wakeUp() { // 唤醒处理 }

这个温湿度监测项目不仅展示了STM32与SHT40的完美配合,更体现了嵌入式系统开发的完整流程。从硬件连接到软件实现,从基础功能到高级优化,每个环节都蕴含着丰富的技术细节。在实际部署中,我发现传感器的安装位置对测量精度影响很大,建议通过延长线将传感器安装在最具代表性的位置,同时保持主控板在易于操作的位置。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 15:19:55

SpringBoot集成Redis Stream:从基础配置到消费组实战

1. 为什么需要Redis Stream&#xff1f; Redis Stream是Redis 5.0引入的一种新的数据结构&#xff0c;它专门为消息队列场景设计。相比传统的List、Pub/Sub等方案&#xff0c;Stream提供了更强大的功能&#xff1a; 消息持久化&#xff1a;不像Pub/Sub那样消息发送后就消失消费…

作者头像 李华
网站建设 2026/4/21 15:17:38

别再纠结选哪种了!立体视觉、结构光、TOF深度相机,看完这篇保姆级对比就知道你的项目该用谁

深度相机技术选型实战指南&#xff1a;立体视觉、结构光与TOF的黄金分割点 当你的机器人项目需要一双"慧眼"来感知三维世界时&#xff0c;摆在面前的技术选项往往令人眼花缭乱。市面上主流的深度感知方案——立体视觉、结构光和TOF&#xff0c;就像三种不同性格的助手…

作者头像 李华
网站建设 2026/4/21 15:16:39

如何用RyTuneX优化Windows系统性能:从基础配置到高级调优

如何用RyTuneX优化Windows系统性能&#xff1a;从基础配置到高级调优 【免费下载链接】RyTuneX RyTuneX is a cutting-edge optimizer built with the WinUI 3 framework, designed to amplify the performance of Windows devices. Crafted for both Windows 10 and 11. 项目…

作者头像 李华
网站建设 2026/4/21 15:08:35

GLM-4.1V-9B-Base企业落地:HR招聘简历中证书/成绩单图像结构化提取

GLM-4.1V-9B-Base企业落地&#xff1a;HR招聘简历中证书/成绩单图像结构化提取 1. 企业招聘场景中的痛点 在HR日常招聘工作中&#xff0c;处理大量候选人简历中的证书和成绩单是一项耗时费力的工作。传统方式需要人工逐页查看PDF或图片格式的附件&#xff0c;手动记录关键信息…

作者头像 李华