1. 项目概述与核心需求
去年接手了一个工业环境监测项目,需要开发一套稳定可靠的温湿度采集系统。经过技术选型,最终决定采用C#开发上位机程序,通过Modbus RTU协议与下位机通信。这个项目最核心的需求是实现:
- 实时采集多个节点的温湿度数据
- 数据可视化展示(曲线图+仪表盘)
- 异常状态预警通知
- 历史数据存储与查询
在工业现场,温湿度监控对生产质量至关重要。比如在制药车间,环境湿度必须控制在45%-65%之间,超出范围就需要立即报警。这就要求我们的采集程序必须做到:
- 通信稳定可靠(Modbus RTU协议)
- 数据更新及时(多线程处理)
- 界面响应流畅(异步UI更新)
- 长期运行不崩溃(完善的异常处理)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 分层架构实现
采用经典的三层架构设计:
code复制表示层(UI)
↓
业务逻辑层(BLL)
↓
数据访问层(DAL)
这种架构的优势在于:
- 各层职责明确,便于维护
- 可单独替换某一层实现(如更换数据库)
- 方便团队协作开发
数据访问层使用SQLite作为本地存储方案,主要考虑:
- 零配置,无需安装数据库服务
- 单文件存储,便于部署
- 支持标准SQL语法
- 读写性能满足采集场景需求
2.2 核心模块设计
通信模块
csharp复制public class ModbusRTUClient
{
private SerialPort _serialPort;
private byte _slaveAddress;
public bool Connect(string portName, int baudRate)
{
// 串口参数配置
_serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
_serialPort.Open();
return _serialPort.IsOpen;
}
public float ReadHoldingRegister(ushort address)
{
// 构造Modbus RTU请求帧
byte[] request = new byte[8];
request[0] = _slaveAddress;
request[1] = 0x03; // 功能码
// ...填充寄存器地址等
_serialPort.Write(request, 0, request.Length);
// 解析响应数据
byte[] response = new byte[256];
int bytesRead = _serialPort.Read(response, 0, response.Length);
// 数据校验与转换
return ConvertToFloat(response);
}
}
数据采集模块
采用生产者-消费者模式:
- 采集线程定时读取设备数据(生产者)
- 数据存入缓冲队列
- 处理线程从队列取出数据(消费者)
- 进行数据校验、存储和界面更新
这种设计避免了直接操作UI控件导致的线程安全问题。
3. 关键实现细节
3.1 串口通信优化
工业现场常见问题及解决方案:
-
数据粘包问题
- 现象:多条报文粘连在一起
- 解决:严格遵循Modbus RTU的3.5字符间隔时间
csharp复制_serialPort.ReadTimeout = 100; // 毫秒 _serialPort.ReceivedBytesThreshold = 1; // 触发事件的最小字节数 -
通信超时处理
csharp复制try { _serialPort.Write(request, 0, request.Length); DateTime start = DateTime.Now; while (_serialPort.BytesToRead < expectedLength) { if ((DateTime.Now - start).TotalMilliseconds > timeout) throw new TimeoutException(); Thread.Sleep(10); } } catch(TimeoutException ex) { // 重试或记录错误 } -
CRC校验
Modbus RTU要求严格的CRC校验:csha复制
