工业数据采集和监控这活儿,说难不算难,说简单也不简单。难点不在于Modbus协议有多复杂,而在于一套系统要把串口通信、界面刷新、数据存储、报警处理这些事情都理顺,还不能互相拖后腿。
最近在做一个工业冷却系统的上位机项目,正好走了一遍从硬件通信到界面展示的完整流程。这套方案基于WPF,通过Modbus RTU协议跟下位机设备打交道,采集到的数据实时展示在界面上,同时存进SQL Server。文章整理了项目中的一些设计和实现细节,供有类似需求的同行参考。
项目介绍一个基于WPF的SCADA类数据采集与监控系统,主要面向工业冷却场景。系统通过Modbus RTU协议与下位机设备通信,实时采集温度、压力、流量等运行参数,在WPF界面中动态展示,并将数据存入SQL Server数据库以便后续查询和分析。
项目结构采用了分层设计,分为通信层(SerialPort通信与Modbus协议封装)、数据访问层(DAL)、业务逻辑层(BLL)、视图层(View)和视图模型层(ViewModel),以及自定义控件库。
项目功能Modbus RTU数据采集:通过串口与下位机通信,读取保持寄存器中的数据,支持浮点数解析(大端AB CD格式)
实时数据监控:在WPF界面中动态更新设备参数,包括温度、压力、流量等关键指标
自定义图形控件:冷却塔、冷却水泵、管道流动画等工业设备图形组件,直观呈现设备状态
阈值报警机制:当监控数值超过上下限时,界面自动触发报警信息并记录
数据持久化:将实时数据存入SQL Server数据库,支持历史数据追溯
设备与点位管理:通过数据库表管理设备信息、监控点位和存储区配置
日志记录:记录系统运行日志和报警信息,便于问题排查
项目特点分层架构清晰:按MVC模式变体组织,通信层、业务层、视图层职责分明,易于扩展和维护
实时性较好:通过独立线程或定时器驱动采集循环,界面数据刷新流畅
报警机制完备:数值越限时自动触发报警并记录,支持报警状态显示与历史查询
自定义控件复用:冷却塔、水泵、管道等图形控件封装良好,可复用于不同项目
配置化设计:串口参数、从站地址、寄存器映射等信息通过配置文件或数据库管理,减少硬编码
工业场景适配:面向冷却系统、水处理等典型工控场景,非通用业务系统
项目技术技术项
选型
说明
开发语言
C#
.NET平台主流语言
UI框架
WPF
桌面端图形界面开发
通信协议
Modbus RTU
工业串行通信标准协议
数据库
SQL Server 2026
数据持久化存储
数据库
SQL Server Management Studio 2022
数据库管理与查询
架构模式
分层架构(类似MVVM)
界面与业务逻辑分离
开发环境
Visual Studio
集成开发环境
项目代码目录结构项目按功能模块组织,层次清晰:
├── Communication/ # 类库:串口通信层│ ├── Modbus/RTU.cs # Modbus RTU协议实现│ └── SerialInfo.cs # 串口配置模型├── Controls/ # 类库:自定义控件│ ├── CircularProgressBar.xaml(.cs) # 环形进度条控件│ └── Components/│ ├── ComponentBase.cs # 设备组件基类│ ├── CoolingTower.xaml(.cs) # 冷却塔图形组件│ ├── CoolingPump.xaml(.cs) # 冷却水泵图形组件│ └── Pipeline.xaml(.cs) # 管道流动画组件└── DataAcquisitionAndMonitoringSystem/ # WPF主项目├── /Base/ # 基础设施│ ├── CommandBase.cs # ICommand实现│ ├── NotifyPropertyBase.cs # INotifyPropertyChanged实现│ ├── GlobalMonitor.cs # 全局监控核心循环│ └── Converter/ # 值转换器├── /Model/ # 数据模型│ ├── DeviceModel.cs # 设备模型│ ├── MonitorValueModel.cs # 监控点位模型│ └── LogModel.cs # 日志模型├── /DAL/ # 数据访问层│ └── DataAccess.cs # SQL Server数据操作├── /BLL/ # 业务逻辑层│ ├── IndustrialBLL.cs # 业务逻辑处理│ └── DataResult.cs # 通用结果包装├── /ViewModel/ # 视图模型│ ├── MainViewModel.cs # 主窗口VM+导航│ └── SystemMonitorViewModel.cs # 系统监控页VM└── /View/ # 视图├── SystemMonitor.xaml(.cs) # 系统监控主界面└── ReportManagement.xaml(.cs) # 报表页(预留)核心代码说明Modbus RTU通信层
通信层封装了Modbus RTU协议的读写操作,包括功能码3(读保持寄存器)的实现。串口通信采用超时控制,单次请求超时不影响后续轮询。
// 串口配置模型public SerialInfo{public string PortName { get; set; }public int BaudRate { get; set; }public int DataBits { get; set; }public StopBits StopBits { get; set; }public Parity Parity { get; set; }}全局监控核心循环
GlobalMonitor类负责驱动整个采集循环,按配置的间隔轮询各从站设备,读取寄存器数据并触发界面更新和报警检查。
字节转浮点扩展
下位机返回的数据是字节数组,需要根据Modbus的数据格式转换为浮点数。项目中实现了大端AB CD格式的浮点数转换方法。
数据库设计系统使用三张核心表:
devices:设备表,存储冷却塔等设备的基本信息
monitor_values:监控信息表,存储各设备的实时监控数据
storage_area:存储区表,配置各从站的寄存器映射关系
项目效果在实际运行中,这套系统的使用流程大致是这样的

先用VSPD虚拟串口工具创建一对串口(比如COM1和COM2),程序这边连COM1,Modbus Slave模拟软件那边连COM2。在Modbus Slave中把从站ID设为1,存储区设置为03保持寄存器,起始地址0,长度36。


启动程序后,界面会显示冷却塔的图形组件和各监控参数。往Modbus Slave的寄存器里填数值(浮点数格式选大端AB CD),程序就能实时读取并更新界面上的温度、压力等数据。当数值超过设定的上下限时,界面下方会自动出现报警信息,比如“冷却塔1。当前值:100”。

总结这套数据采集与监控系统解决了一个很实际的问题:如何用一套清晰的架构把Modbus通信、界面展示、数据存储和报警处理串起来。它没有把全部代码塞进MainWindow.xaml.cs里,而是通过分层设计让各个模块各司其职——通信层专心跟串口打交道,业务层处理数据转换和逻辑判断,界面层只负责展示和用户交互。
对于正在做工控上位机项目的人来说,这个项目的参考价值在于看到一种可行的分层方式。Modbus RTU协议本身不难,难的是当设备数量增加、数据量变大、报警逻辑变复杂的时候,代码还能不能保持清晰可维护。这套方案在冷却系统场景中跑通了,稳定可靠。