Modbus RTU通常是「半双工」的(可以发送和接收,但不能同时进行), 特别是在 「RS-485」 总线上(两根线传输数据):
「主站(Master)」 先发送一个包含从站地址、功能码、数据、CRC校验的报文。
「从站(Slave)」 接收到报文后,检查地址是否匹配:
整个通信过程中,同一时间总线上「只能有一个设备发送」,主从站不能同时发数据。
所以底层的串口通信驱动的基本流程是发送请求报文, 之后接收报文, 上位机作为Modbus主站, 串口驱动包含三个方法, 打开串口, 关闭串口, 发送接收
安装数据转换库NuGet包
串口通信接收到的报文都是字节流数据, 所以涉及到很多数据转换, 这里推荐下载一个数据转换包, 这个包封装了大量数据转换方法, 可以提高后续的开发效率
打开关闭串口方法
串口通信的参数包括端口号, 波特率, 数据位, 奇偶校验, 停止位, 所以打开串口方法OpenSerialPort需要提供这些参数
关闭串口方法CloseSerialPort就简单很多, 判断当_serialPort对象不为空且打开才执行Close方法
发送接收数据方法
串口发送接收方法SendAndRcv基本流程就是发送, 发送后接收, 往复循环
但是如果只是简单的这样写, 会出现很多问题, 比如超时了怎么办, 读写同时进行怎么处理, 数据是否完整接收, 这些问题都要考虑, 所以在基础功能上需要添加
[功能1]清空串口缓冲区,避免残留数据影响本次通信
[功能2]判断超时
[功能3]已收到数据且连续5次未检测到新数据,认为数据接收完毕
[功能4]异常捕获
[功能5]锁机制
完善后的代码如下
测试
测试需要串口调试工具, 如果没有实际的串口设备, 还需要使用虚拟串口工具, 这里推荐一个工具, 具备了以上两个功能
https://github.com/SuperStudio/SuperCom
在FrmMain中添加如下代码进行测试
资源管理器结构
新建一个类库, 创建一个Base文件夹, 新建一个SerialBase.cs类, SCADAPlatform项目中引用此类库
资源管理器结构如下图
下一节内容: Modbus读线圈功能开发