
去年给家里做智能家居改造时一直困扰我的不是传感器选型也不是继电器驱动而是“人机交互”这一块。手机App控制当然方便但每次开关灯、看数据都要掏手机解锁打开App时间一长就觉得很繁琐。后来接触到迪文屏和DGUS组态开发发现这东西非常适合做墙面固定面板——串口一接、变量一配就能做出带触摸的彩色控制界面不用自己折腾复杂的GUI库。再加上一颗STM32做数据采集和逻辑联动整套系统的完整度一下子就上来了。这篇就把我这次用迪文屏做温湿度控制面板的过程拆开揉碎讲清楚硬件选型、DGUS工程配置、STM32端协议代码、常见坑位一次性整理出来。1. 整体设计与思路拆解1.1 需求定位面板到底要解决什么问题这套智能家居控制面板的项目需求并不复杂核心是三个把环境温湿度数据以直观、美观的方式显示在墙面上允许用户通过触摸直接设置温湿度上下限阈值当温度或湿度越限时STM32负责输出控制信号去驱动风扇、加湿器这类外部负载。也就是说面板并不是一个单纯显示的数码管温度计而是“显示 输入 联动控制”的完整节点。很多初学者有一个思维定式想做界面就上正点原子的RGB屏然后移植LVGL或emWin。这个路线可行但代价是学习成本很高而且每次改界面布局都要重新编译固件、重新烧录效率很低。这个项目里我选择迪文屏核心逻辑就是“数据和界面分离”——界面布局、图片切图、控件配置全部在PC端完成生成配置文件下载到屏幕Flash运行时STM32只负责往指定变量地址写数据屏幕就会自动刷新显示内容。触摸事件的回传也一样用户按了哪个按钮屏幕会把对应的键值或数据通过串口发给STM32由STM32来决定下一步逻辑。这一套流程对单片机的性能要求极低对开发效率的提升却很可观。1.2 系统架构与工作流程整套系统的数据流可以拆成三个环节采集环节STM32通过GPIO或I2C读取温湿度传感器DHT11/DHT22/SHT30得到当前环境的温度和湿度值。交互环节STM32将温湿度数值通过串口发送给迪文屏指定变量地址屏幕实时更新显示同时用户通过屏幕的触摸控件设置目标阈值屏幕将用户输入的数据回传给STM32。执行环节STM32将采集值与阈值做比较通过PID或滞回逻辑控制继电器继电器再驱动风扇、加热器、加湿器等负载。这个架构最大的优点是耦合度低。如果你以后想换LCD屏只需要保证串口协议不变改显示层的物理实现即可如果要加更多传感器STM32端加采集代码就行屏幕上预留好变量地址就能直接显示新数据。实际上这也是工业HMI常见的设计套路MCU专注于控制逻辑屏幕专注于显示交互。1.3 硬件选型与成本权衡硬件清单如下模块型号/规格作用参考成本主控MCUSTM32F103C8T6数据采集、通信、逻辑控制约10元温湿度传感器DHT11 / DHT22 / SHT30环境温湿度采集5-25元迪文屏DMG80480C070_04WTC7寸人机交互显示与触摸150-250元继电器模块5V单路/双路控制风扇、加湿器等负载5-15元电源12V/5V双输出电源模块系统供电20元选STM32F103C8T6不是因为性能多强而是因为资料多、价格低、入门门槛低就算新手也能很快上手标准库或HAL库开发。传感器这里我推荐SHT30精度比DHT11高一个量级而且是I2C接口代码写起来比DHT11的单总线时序要简单很多。不过考虑到很多人手里只有DHT11后面我会把两种都提一下。迪文屏选7寸电容屏是因为作为墙面面板显示面积大一些数字和触摸区域不会显得局促如果板材开孔尺寸有限4.3寸的DMT48270C043也完全可以下位机代码几乎不需要改动。2. DGUS开发核心细节与实操要点2.1 DGUS到底是什么跟普通串口屏有什么区别迪文屏之所以叫“智能屏”核心在于它内部运行着一套DGUS系统这套系统把传统的“屏幕外设”变成了“变量映射终端”。DGUS的全称是DGUS Graphic Utility Software它定义了一套变量地址与显示/触控控件的映射关系。你在PC端的DGUS软件里在背景图片上放置一个“数据变量显示”控件指定它显示内存地址0x1000处的数据再设置数据类型为无符号整型下载到屏幕后只要串口收到指令往0x1000地址写入新数值屏幕上的对应位置就会自动刷新成新的数字。整个过程完全不涉及屏幕端的代码编程界面交互逻辑全部通过配置文件描述。这里有一个非常重要的思维转换不要再去想“屏幕执行代码”这件事。DGUS屏的运行模式是——屏幕负责“画”MCU负责“算”。屏幕把用户的触摸行为转换成数据帧发给MCUMCU把要显示的数据按协议发给屏幕屏幕只是忠实呈现。理解了这一点整个开发思路就清晰多了也不会在后期联调时搞混“数据到底存在谁那里”的问题。2.2 变量地址规划方案一份好的变量地址表是整个项目的地基。地址规划不好后面写代码和配置控件容易混乱甚至出现地址覆盖导致数据错乱。建议按功能模块划分地址区间地址长度数据类型含义0x10001 Word带符号整数当前温度值放大10倍0x10011 Word带符号整数当前湿度值放大10倍0x11001 Word无符号整数温度上限设置值0x11011 Word无符号整数温度下限设置值0x12001 Word无符号整数湿度上限设置值0x12011 Word无符号整数湿度下限设置值0x13001 Word无符号整数联锁/手动模式切换标志0x13011 Word无符号整数继电器开关状态反馈地址规划的原则是显示数据区、设置参数区、控制状态区完全分开。显示数据是只读的MCU单方向往屏上写设置参数是双向的用户触摸写入后MCU要能读回来控制状态则是状态反馈用于屏幕显示当前继电器是开还是关。按区间划分后无论是你写代码还是后续调试出了故障都能快速定位是哪个区的问题。2.3 DGUS工程配置流程用DGUS做界面最核心的步骤在PC端完成。以7寸屏为例流程如下准备一张800×480的底图。不要用自带的美观图片模板建议用制图软件做一张深色背景、带清晰数字区域的工业风底图底图上温度显示区、湿度显示区、阈值设置区、按钮区域都要规划好坐标。用DGUS软件新建工程选择对应的屏型号。这里一定要选对型号比如DMG80480C070对应的是T5L1芯片平台如果用T5L2的配置下载工程后会出现莫名其妙的花屏。导入底图后在图片上放置控件。首先放“数据变量显示”控件设置变量地址0x1000数据类型为有符号整数整数位数3位小数位数1位因为我们在STM32端把温度放大10倍发送。然后放“触摸设置”控件地址设为0x1100设置类型选择“上限值”取值范围0到600。配置返回到“设置页面”的按钮按下后清空当前输入焦点或跳转页面这个看具体需求。编译工程生成DWIN_SET文件夹将这个文件夹整个拷贝到SD卡的根目录把SD卡插入屏幕背面卡槽上电后屏幕会自动升级配置文件等待蓝屏或提示完成即可。这里有个极其容易踩的坑是SD卡升级问题。迪文屏对SD卡的要求比较严格最好使用FAT32格式、容量不超过16G的卡且卡内不要套文件夹DWIN_SET文件夹必须是根目录下唯一运行目录。升级过程中屏幕如果直接停在开机画面不动基本就是配置文件和屏型号对不上或者SD卡格式有问题。2.4 显示控件数据类型的选择DGUS里的数据变量显示控件支持多种格式无符号整型、有符号整型、长整型、浮点型、字符串等。温湿度显示这里最常见的坑是负数温度的处理。冬天环境温度可能降到零下如果用无符号整型-5℃会被显示成65531非常离谱。所以温度值在STM32端发送时建议统一放大10倍用有符号整型表示-5℃对应-50。这样DGUS端只要设置小数位数为1位显示出来就是-5.0干净利落。湿度同理放大10倍后显示。这是在工程配置阶段就要确定下来的约定不然后面改起来也很麻烦。3. STM32端逻辑实现与协议联调3.1 底层硬件初始化STM32端主要用到两个外设I2C读取SHT30或单总线读取DHT11以及USART1与迪文屏通信。时钟配置这里不多讲直接说几个关键点开启I2C1和USART1的时钟配置USART1为115200-8-N-1模式。迪文屏默认波特率115200但T5L平台可以通过配置文件设置波特率。为了稳定性建议115200不高不低线缆稍长也不容易出错。GPIO方面SHT30的SCL和SDA要配置为开漏输出并外接4.7k上拉电阻如果是DHT11则数据引脚配置成推挽输出/开漏输出切换的模式按单总线时序进行读写。USART1的TX/RX直接接迪文屏的RXD/TXD注意是屏的RXD接STM32的TX交叉连接。有些屏的接口电平是3.3V TTLSTM32F103也是3.3V可以直接互连如果使用5V供电的MCU或屏需要加电平转换模块否则容易烧引脚。3.2 温湿度采集与数据处理传感器选SHT30为例它通过I2C读取。SHT30有两种读取模式周期采集模式和单次采集模式。控制面板场景下建议用周期采集让传感器每秒自动出数据MCU定时读取最新值即可这样MCU不用去触发测量逻辑更简洁。SHT30的周期模式配置命令是0x2236每秒重复采集。读取数据时从0x24开头地址读取6字节其中温度数据是两个字节MSB和LSB湿度同理。原始AD值要转成物理值温度 -45 175 * (raw / 65535)湿度 100 * (raw / 65535)。计算出来是浮点型为了DGUS显示方便我们乘以10转成整数存储发送时按整型发送即可。如果不放大直接在DGUS里配置成浮点显示也行但浮点格式的串口传输涉及IEEE754格式STM32端要内存拷贝发送会稍微繁琐一点。整数加固定小数位是更稳妥的通行做法。3.3 迪文屏串口协议封装迪文屏的串口指令格式遵循“帧头 长度 指令 数据”的结构。最常见的两条指令是写变量地址指令0x82格式为 5A A5 长度 82 地址高字节 地址低字节 数据...。长度 3 2 * 数据字数Word。读变量地址指令0x83格式为 5A A5 长度 83 地址高字节 地址低字节 读取字数。屏幕返回同样的帧格式数据区带上读到的值。比如往0x1000地址写温度值250表示25.0℃指令就是5A A5 05 82 10 00 00 FA这里05是长度82是写指令10 00是地址00 FA是数据250的十六进制。如果是写两个地址连续的数据长度相应增加即可。STM32端只需要用sprintf格式化一个缓冲区然后通过串口发送即可。发送频率不用太高每秒2次显示刷新足够。读取用户设置阈值时STM32周期性向屏幕发送读指令比如读0x1100地址5A A5 04 83 11 00 01返回帧中会带上当前0x1100的值。STM32解析返回帧时要按帧头、长度、指令、地址、数据逐字节校验。特别注意长度字段和数据区的对应关系很多人在解析时少算或多算一个字节导致读出来的值全是乱的。3.4 联动控制逻辑与继电器输出联动控制不需要太复杂但要做对逻辑避免负载频繁抖动。我采用的是滞回控制方式。温度控制当温度大于上限时继电器1吸合输出高电平驱动风扇或空调启动当温度回落到上限减1℃以下时才断开继电器。湿热控制湿度同理低于下限时启动加湿器高于下限加2%时才关闭。滞回区间的作用是防止继电器在临界点来回吸合延长继电器寿命。如果你用的是继电器模块来控制交流负载建议把频繁切换的时间间隔至少设置为10秒以上不然触点寿命会急速下降。控制状态通过变量地址0x1301实时写回屏幕显示这样用户能直观看到当前继电器是ON还是OFF状态而不是盲猜。3.5 关键代码框架这里给出一份简化版的代码骨架方便你理解整个数据流和协议层的写法。// 发送温湿度到屏幕 void Dwin_Report_TempHum(int16_t temp, int16_t hum) { uint8_t buf[16]; buf[0] 0x5A; buf[1] 0xA5; buf[2] 0x05; // 长度 3 2*1 buf[3] 0x82; buf[4] 0x10; // 地址高字节 buf[5] 0x00; // 地址低字节 buf[6] (uint8_t)(temp 8); buf[7] (uint8_t)(temp 0xFF); HAL_UART_Transmit(huart1, buf, 8, 100); buf[4] 0x10; buf[5] 0x01; buf[6] (uint8_t)(hum 8); buf[7] (uint8_t)(hum 0xFF); HAL_UART_Transmit(huart1, buf, 8, 100); } // 读取屏幕阈值变量返回0x83读取帧 void Dwin_Read_Threshold(void) { uint8_t buf[8]; buf[0] 0x5A; buf[1] 0xA5; buf[2] 0x04; buf[3] 0x83; buf[4] 0x11; buf[5] 0x00; buf[6] 0x00; buf[7] 0x01; HAL_UART_Transmit(huart1, buf, 8, 100); }接收中断里解析返回帧判断帧头和长度后取出数据区第3、4字节拼接为16位阈值保存。控制逻辑这一块用简单的状态机就够了void Temp_Control_Loop(void) { if (current_temp threshold_temp_high) { relay1_on(); } else if (current_temp (threshold_temp_high - 10)) { relay1_off(); } }这里的减法10代表滞回区间10个计数单位即1℃。具体滞回范围根据你的设备特性调整。4. 常见问题与排查技巧实录4.1 屏幕下载配置后花屏或白屏多半是工程型号和屏幕型号不匹配。T5L平台分为T5L0、T5L1、T5L2DGUS软件里工程创建时选的型号必须和屏背面的标签一致尤其是UI内核版本不一致的情况下升级配置很容易白屏。还有一种可能是SD卡容量过大部分屏幕对32GB甚至64GB的卡支持不好换一张8G的旧卡格式化成FAT32分配单元大小32KB基本就能解决。4.2 串口发送数据变量没有变化检查三个地方地址是否写错特别是十六进制换算错误数据显示控件的数据类型是否和发送的数据格式匹配有无符号、小数位是否一致发送的帧长度是否计算正确。0x82指令的字节长度计算方式是长度 3 2*NN是连续写入的字数。如果这条搞错了屏幕端会丢弃整帧自然不会有任何反应。还有一个容易忽略的点DGUS控件属性里有一个“显示方式”默认是覆盖显示但如果你误设成了其他模式数据刷新时会出现旧数字残影。4.3 触摸设置无效或者数值跳动触摸设置控件在DGUS里有个“输入范围”设置如果范围设置得太窄超过限制的数据会被自动丢弃。比如温度上限设置范围是0到600你输入650屏幕可能显示成功但实际写入的值是错误的。另外电容屏的触摸有时会因为供电电源纹波过大而出现数值跳动电源部分尽量在STM32的VDD和GND之间加100nF去耦电容在屏幕供电端加一个470uF电解电容大部分抖动能得到缓解。4.4 屏幕回传数据解析不对迪文屏对0x83读指令的应答帧格式是帧头 长度 0x83 地址 数据。注意“长度”字段的数值不固定它是3 2*读取字数。如果你连续读多个字返回的数据会跟着变长。很多人在STM32接收处理时没有做帧同步导致解析到错误位置。推荐方法是在中断里用环形缓冲区接收串口数据主循环里做状态机解析帧头和长度拿到完整一帧后再提取地址和数据不要边收边解析。帧尾不需要校验迪文协议本身没有CRC但做一下帧头校验可以过滤掉杂波。4.5 继电器频繁吸合抖动这是所有控制面板类项目都容易遇到的痛。负载在临界值附近反复切换不但吵还容易烧触点。解决办法就是前面说的滞回控制。滞回区间大小要根据现场实际负载调整比如控制空调启动时要设置至少2℃的回差控制加湿器则要设置3%以上的回差。另外如果继电器驱动的是感性负载如风扇电机建议在继电器输出端并联一个RC吸收电路典型值100Ω电阻加0.1uF电容串联可以有效减少电弧和电磁干扰。这个细节很多初学者会忽略但晚了接上就会发现STM32偶尔死机其实就是继电器吸合瞬间产生的EMI干扰到了MCU的电平。5. 其他细节与项目后续扩展5.1 屏幕底图和界面设计技巧迪文屏的显示效果很大程度取决于你给的底图质量。用纯黑色底加细线条分割区域配合白色大号字体显示效果会非常“智能家居”。不要直接拿示例工程的图片来用明显有套模板的感觉。字号方面温度数值建议用到80号以上字体人站在两三米外能一眼看清触摸按钮的点击区域不要小于60×60像素不然手指容易误触旁边的控件。5.2 项目还能怎么扩展这套系统的框架做好后扩展非常方便。想加入MQTT联网上报温度STM32外接ESP8266或ESP32模块把读取到的温湿度通过MQTT发布到Home Assistant即可。想加入更多控制通道在DGUS底图上增加一个区域的按钮地址规划在0x1400代码里再加一路继电器控制逻辑就行。想把数据存起来做曲线显示DGUS部分型号支持曲线控件把历史数据依次写入曲线缓冲区地址即可。整体来说迪文屏加STM32这套组合的优点是做出来的东西直接能安装上墙显示稳定不掉线程序跑个一年半载也不用操心。5.3 成本和时间投入说明整个项目硬件成本控制在150到250元之间大头是屏幕。如果手头刚好有旧智能手机拆机屏也可以考虑走ESP32方案但“DIY的触摸屏面板”的质感和迪文屏其实差得很远。软件开发时间方面如果你完全没接触过DGUS第一次从头到尾做到底、包括屏幕界面和STM32代码大概需要2到3天如果做过一次后面再做第二个面板一天之内就能搞定。这个项目最值得学习的地方倒不在于代码多高深而是“串口屏 MCU”这种在工业领域非常成熟的架构搬到智能家居DIY里一样非常好用。它让我真正意识到所谓智能家居不一定是全屋设备都接入云端才好用有时候一个挂在墙上的实体面板反而比手机App更快更直接。我后来把家里的客厅灯和阳台窗帘也接到了这套系统里用下来半年多稳定性确实比之前用便宜WiFi模块的方案靠谱得多。如果你也在做类似的智能家居项目真心建议试试用串口屏这条路线省心、可控、效果直观。用迪文屏和STM32做联动控制无论是毕设还是实际部署都是一套能快速出成果的组合。