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

张开发
2026/4/21 15:20:24 15 分钟阅读

分享文章

手把手教你用零知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时钟线可自定义其他IOPA4SHT40 SDA软件I2C数据线需上拉4.7k电阻PB10TFT_CS屏幕片选信号SPI片选PB11TFT_DC数据/命令选择PB12TFT_RST屏幕复位信号可接MCU复位PB13TFT_SCKSPI时钟线硬件SPI时钟PB15TFT_MOSISPI数据输出硬件SPI数据线PA0按键输入界面切换控制内部上拉接地触发3.3V传感器电源为SHT40和TFT供电确保电源稳定GND共地连接所有器件的地线连接避免地环路干扰接线注意事项I2C总线需要上拉电阻通常4.7kΩTFT屏幕的背光可能需要单独供电长距离连接时考虑使用屏蔽线减少干扰2. 开发环境搭建2.1 零知IDE基础配置零知IDE为STM32开发提供了便捷的环境下载并安装最新版零知IDE官网提供Windows/macOS版本安装STM32支持包# 在零知IDE的包管理器中搜索并安装 STM32F1xx_DFP - STM32F1系列设备支持包配置板卡选项选择开发板类型STM32F103RBT6设置调试接口SWD配置时钟源8MHz外部晶振2.2 必要库的安装本项目需要以下关键库支持传感器驱动Adafruit_SHT4x_Library显示驱动Adafruit_ST7789图形库Adafruit_GFX软件I2CSoftWire安装方法// 在零知IDE的库管理器中搜索并安装 1. 搜索SHT4x → 安装Adafruit_SHT4x 2. 搜索ST7789 → 安装Adafruit_ST7789 3. 搜索SoftWire → 安装Software I2C库2.3 项目基础配置创建新项目后需要进行以下关键配置启用硬件SPI在hal_conf.h中取消注释#define HAL_SPI_MODULE_ENABLED设置优化级别项目属性 → C/C构建 → 设置优化为-O2配置串口调试启用USART1波特率1152003. 核心代码实现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 i0; i6; 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 i0; iendAngle; 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 多界面切换设计实现四个信息展示界面的平滑切换温度界面环形温度计数字显示湿度界面环形湿度计百分比显示VPD界面仪表盘环境评估信息界面传感器参数系统状态// 绘制湿度界面 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 i0; iendAngle; 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 i0; iSAMPLE_SIZE; i) { sum tempHistory[i]; } return sum / SAMPLE_SIZE; }5. 项目优化与调试5.1 常见问题排查问题1传感器无响应或读数错误解决方案检查I2C线路连接是否正确确认电源电压稳定(3.3V±10%)降低I2C时钟速度测试添加I2C上拉电阻(4.7kΩ)问题2TFT显示异常解决方案确认SPI引脚配置正确检查屏幕背光供电调整屏幕初始化延迟尝试降低SPI时钟速度问题3按键响应不稳定解决方案添加硬件消抖电路(0.1μF电容)调整软件防抖时间检查上拉电阻是否有效5.2 性能优化技巧SPI优化启用DMA传输使用双缓冲机制// 示例SPI DMA配置 SPI_DMA_Init(); SPI_DMA_Enable();电源管理添加LC滤波电路使用低噪声LDO稳压器在代码中实现睡眠模式内存优化将大字体数据放入Flash使用内存池管理动态分配// 将字体数据存入Flash const uint8_t fontData[] PROGMEM {...};5.3 扩展功能建议数据记录添加SD卡模块存储历史数据实现CSV格式数据导出无线传输集成ESP8266实现WiFi上传使用蓝牙模块进行手机连接报警功能设置温湿度阈值报警添加蜂鸣器和LED指示灯云端监控对接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 外壳设计与安装一个专业的项目离不开精良的外壳设计3D打印方案使用PLA材料打印定制外壳设计散热孔和安装支架考虑防水需求时可使用PETG材料PCB设计将电路集成到单一PCB添加电源管理电路设计标准的传感器接口安装建议避免阳光直射影响温度测量保持传感器周围空气流通远离热源和潮湿区域6.2 多传感器融合提升系统功能性的几种扩展方案CO2传感器SCD30或MH-Z19气压传感器BMP280光照传感器BH1750空气质量传感器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 低功耗优化对于电池供电的应用场景硬件优化选择低功耗版本STM32使用高效率DC-DC转换器添加电源开关电路软件优化实现深度睡眠模式降低采样频率优化显示刷新策略// 低功耗模式实现 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的完美配合更体现了嵌入式系统开发的完整流程。从硬件连接到软件实现从基础功能到高级优化每个环节都蕴含着丰富的技术细节。在实际部署中我发现传感器的安装位置对测量精度影响很大建议通过延长线将传感器安装在最具代表性的位置同时保持主控板在易于操作的位置。

更多文章