DC娱乐网

WPF + Modbus RTU 一套 SCADA监控系统的实现

前言工业数据采集和监控这活儿,说难不算难,说简单也不简单。难点不在于Modbus协议有多复杂,而在于一套系统要把串口通信
前言

工业数据采集和监控这活儿,说难不算难,说简单也不简单。难点不在于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协议本身不难,难的是当设备数量增加、数据量变大、报警逻辑变复杂的时候,代码还能不能保持清晰可维护。这套方案在冷却系统场景中跑通了,稳定可靠。