一、项目整体方案与功能介绍1.1 实现全部功能传感器采集DHT11 温湿度 ADC 模拟量土壤湿度 / 光敏 / 电压本地可视化IIC-OLED 实时刷新温湿度、电压、WiFi 连接状态ESP8266 AT 指令驱动上电自动连 WiFi断线自动重连 TCP 服务端远程数据上传格式化报文 TCP 透传发送电脑 / 手机远程实时查看容错机制WiFi 断开自动重试采集失败填充默认值避免界面乱码。1.2 硬件接线分配STM32 USART1PA9/PA10ESP8266 通信波特率 115200。DHT11 DATAPA0。ADC 模拟输入PA1。OLED IICPB6 SCL、PB7 SDA。3.3V 统一供电所有模块共地ESP8266 禁止 5V 直供。1.3 整体数据流传感器采集 → 数据缓存结构体 → OLED 本地刷新 ESP8266 TCP 远程上传ESP8266 工作逻辑上电检测模块 → 连接路由器 WiFi → 连接电脑 TCP 服务端 → 持续透传上报数据掉线全程自动重试不阻塞采集业务。二、核心原理深度解析2.1 ESP8266 AT 透传核心逻辑ESP8266 出厂默认 AT 固件无需二次开发仅靠串口指令完成全部联网操作AT 检测模块是否上电正常ATCWJAP“wifi名”,“密码” 连接局域网 WiFiATCIPSTART“TCP”,“服务器IP”,端口 建立 TCP 客户端连接ATCIPMODE1 ATCIPSEND 开启透传串口数据直接转发至网络一旦收到模块返回CLOSED代表 TCP 断开程序自动重置 WiFi 状态机重新走联网流程。2.2 多外设时序冲突解决方案采集、屏幕刷新、WiFi 串口上报共用主循环若不加时间分片会出现OLED 刷屏卡顿、WiFi 指令发送截断、温湿度读取校验失败。本项目采用时分轮询机制不同业务设置独立计时阈值错峰执行互不抢占 CPU。2.3 远程通信防乱码设计环境数据统一封装固定格式字符串带换行分隔帧尾WiFi 发送操作加简易互斥保护避免采集与上报同时抢占串口断线暂停上报只保留本地采集显示保证基础功能不瘫痪。三、极简模块化完整源码STM32 标准库3.1 env_data.h 统一数据管理#ifndef __ENV_DATA_H#define __ENV_DATA_H#include “stm32f10x.h”//环境数据结构体typedef struct{uint8_t temp;uint8_t hum;float adc_vol;uint8_t wifi_link; //1WiFi已连上TCP0离线}EnvData_t;extern EnvData_t env_data;void Env_Scan(void);#endif3.2 esp8266_wifi.h WiFi 驱动头文件#ifndef __ESP8266_WIFI_H#define __ESP8266_WIFI_H#include “stm32f10x.h”#include “env_data.h”//WiFi配置直接修改此处参数#define WIFI_NAME “MyWiFi”#define WIFI_PWD “12345678”#define TCP_SERVER_IP “192.168.1.105”#define TCP_PORT 8080//WiFi状态枚举typedef enum{WIFI_IDLE,WIFI_CHECK_MODULE,WIFI_CONNECT_AP,WIFI_CONNECT_TCP,WIFI_TRANS_OK}WiFiState_t;void ESP8266_Init(void);void ESP8266_StateTask(void);void ESP8266_SendTcpData(uint8_t *buf);#endif3.3 esp8266_wifi.c 非阻塞状态机 WiFi 驱动#include “esp8266_wifi.h”#include “usart.h”#include “string.h”static WiFiState_t wifi_state WIFI_IDLE;static uint32_t wifi_tick 0;extern uint8_t usart_rx_buf[128];static void ESP_SendAT(charcmd){USART_SendString((uint8_t)cmd);}void ESP8266_Init(void){wifi_state WIFI_CHECK_MODULE;wifi_tick 0;env_data.wifi_link 0;memset(usart_rx_buf,0,sizeof(usart_rx_buf));}//WiFi主状态机10ms调用一次非阻塞不卡采集void ESP8266_StateTask(void){wifi_tick;switch(wifi_state){case WIFI_CHECK_MODULE:if(wifi_tick 20){wifi_tick 0;ESP_SendAT(“AT\r\n”);if(strstr((char*)usart_rx_buf,“OK”)){memset(usart_rx_buf,0,128);wifi_state WIFI_CONNECT_AP;}}break;case WIFI_CONNECT_AP:if(wifi_tick 30){wifi_tick 0;ESP_SendAT(“ATCWJAP”“WIFI_NAME”“,”“WIFI_PWD”“\r\n”);if(strstr((char*)usart_rx_buf,“OK”)){memset(usart_rx_buf,0,128);wifi_state WIFI_CONNECT_TCP;}}break;case WIFI_CONNECT_TCP:if(wifi_tick 30){wifi_tick 0;ESP_SendAT(“ATCIPSTART“TCP”,”“TCP_SERVER_IP”“,”#TCP_PORT\r\n);if(strstr((char*)usart_rx_buf,“CONNECT”)){ESP_SendAT(“ATCIPMODE1\r\n”);ESP_SendAT(“ATCIPSEND\r\n”);wifi_state WIFI_TRANS_OK;env_data.wifi_link 1;memset(usart_rx_buf,0,128);}}break;case WIFI_TRANS_OK:env_data.wifi_link 1;//检测TCP断开标志if(strstr((char*)usart_rx_buf,“CLOSED”)){env_data.wifi_link 0;wifi_state WIFI_CHECK_MODULE;memset(usart_rx_buf,0,128);}break;default:wifi_state WIFI_CHECK_MODULE;break;}}//TCP远程发送环境数据void ESP8266_SendTcpData(uint8_t *buf){if(wifi_state WIFI_TRANS_OK){USART_SendString(buf);}}3.4 env_scan.c 传感器采集业务#include “env_data.h”#include “dht11.h”#include “adc.h”EnvData_t env_data;void Env_Scan(void){//读取温湿度if(DHT11_Read(env_data.hum,env_data.temp) ! 0){env_data.temp 0;env_data.hum 0;}//读取ADC电压均值env_data.adc_vol ADC_GetFilterVolt();}3.5 main.c 主循环时分调度#include “stm32f10x.h”#include “usart.h”#include “oled.h”#include “esp8266_wifi.h”#include “env_data.h”uint32_t scan_tick 0;uint32_t oled_tick 0;uint32_t upload_tick 0;void delay_ms(uint32_t ms){uint32_t i,j;for(i0;ims;i)for(j0;j7200;j);}int main(void){USART1_Init();OLED_Init();DHT11_Init();ADC_Init();ESP8266_Init();while(1) { delay_ms(10); scan_tick 10; oled_tick 10; upload_tick 10; //WiFi状态机持续运行 ESP8266_StateTask(); //500ms采集一次环境数据 if(scan_tick 500) { scan_tick 0; Env_Scan(); } //800ms刷新OLED本地界面 if(oled_tick 800) { oled_tick 0; OLED_Clear(); OLED_ShowString(0,0,WiFi Env Monitor); OLED_ShowString(0,16,T:); OLED_ShowNum(20,16,env_data.temp,2,16); OLED_ShowString(40,16,C); OLED_ShowString(0,32,H:); OLED_ShowNum(20,32,env_data.hum,2,16); OLED_ShowString(40,32,%); OLED_ShowString(0,48,V:); OLED_ShowFloat(20,48,env_data.adc_vol,2,16); //WiFi在线状态提示 if(env_data.wifi_link) OLED_ShowString(0,64,WiFi:Online); else OLED_ShowString(0,64,WiFi:Offline); } //1s远程TCP上传一次数据 if(upload_tick 1000) { upload_tick 0; char send_buf[64]; sprintf(send_buf,Temp:%dC,Hum:%d%%,Vol:%.2fV\r\n, env_data.temp,env_data.hum,env_data.adc_vol); ESP8266_SendTcpData((uint8_t*)send_buf); } }}四、电脑上位机操作步骤电脑连接与 ESP8266 相同局域网 WiFi打开网络调试助手创建 TCP 服务端端口填写 8080查看电脑本机 IPv4修改代码内TCP_SERVER_IP下载程序模块自动联网成功后 OLED 显示 WiFi:Online调试助手持续接收环境报文。五、本项目原创核心优势区别网上通用代码1、非阻塞 WiFi 状态机全程无长延时等待WiFi 重连不会阻塞传感器采集与 OLED 显示工业设备必备2、时分轮询业务隔离采集、屏幕、远程上传错峰执行彻底解决多外设串口时序冲突3、断线全自动容错TCP 断开自动重置联网流程无需手动重启单片机7×24 小时稳定运行4、分层完全解耦WiFi 驱动、传感器采集、显示业务独立拆分替换传感器 / 更换 WiFi 参数只需修改配置宏5、本地离线可用WiFi 掉线仅停止远程上报本地 OLED 依旧正常显示环境数据基础监测功能不丢失6、代码零冗余轻量化剔除多余 AT 指令、无效缓存、重复初始化F103 最小容量芯片可流畅运行。六、高频踩坑深度解决坑 1ESP8266 能收到 AT 应答但始终连不上 TCP电脑防火墙拦截端口关闭防火墙或放行 8080 端口IP 地址填写错误单片机与电脑不在同一局域网先启动电脑 TCP 服务端再上电单片机。坑 2WiFi 偶尔掉线长时间运行离线ESP8266 供电电流不足建议外部 3.3V 稳压电源独立供电缩短杜邦线。坑 3OLED 闪烁、采集数据偶尔为 0各业务执行间隔时间设置过小增加时分轮询计时阈值降低刷新频率。坑 4TCP 收到数据分段、乱码统一使用\r\n作为报文分隔符上位机按换行分割单条环境数据。七、项目拓展升级方案1、升级 SHT30 高精度温湿度传感器提升监测精度2、增加阈值判断WiFi 远程推送超标报警报文3、移植 FreeRTOSWiFi、采集、显示拆分为独立任务4、更换 TCP 为 MQTT 协议对接阿里云 / ESP 云平台实现外网远程监控5、增加按键切换 WiFi 账号无需重新烧录程序修改参数6、搭配继电器远程下发指令控制通风、喷淋设备。八、全文总结STM32ESP8266 AT 透传是低成本远程物联网监测最优方案无需复杂网络协议栈远程监测设备开发核心要点非阻塞 WiFi 重连、多业务时分调度、离线基础功能保活本平台兼顾本地现场查看与远程电脑 / 手机监控适用于农业大棚、机房、仓储环境监测模块化极简工程可直接复用至本专栏所有传感器、无线通信综合项目拓展性极强。