上一个网文我们使用MODSCAN32软件和串口助手调试了Modbus协议,我们之前还分享过使用Qt编写自己的串口助手,今天我们在上次分享的串口助手的源码基础上,使用Qt编写一个Modbus从机程序,让其与MODSCAN32软件实现数据交互。

 

实现目标

熟悉Modbus协议0x03和0x06功能码

 

熟悉QTableView控件的使用

 

Qt编写的Modbus从设备与ModScan32软件进行数据交互

 

结果展示

素材获取

在上面视频中有源码的获取方式,欢迎关注小哈哥的视频号,更多精彩敬请期待。

 

读保持寄存器功能码0x03

当主机发送0x03功能码时,表明主机想要获取从机某些寄存器里的内容。

 

 

举例: 请求读寄存器108~110:

 

 

由上图我们可知,寄存器108的内容为02 2B,即十进制的555,寄存器109~110的内容分别为十六进制的00 00 和 00 64,或十进制的0和100。

 

写单个寄存器功能码0x06

0x06功能码是主机用来向从机的某个寄存器写数据,一次只能操作一个寄存器。

 

使用功能码0x06写单个保持寄存器。

 

 

举例: 请求将十六进制00 03写入寄存器2。

 

 

写多个保持寄存器功能码0x10

 

 

将十六进制 00 0A 和 01 02 写入从寄存器 2 开始的两个寄存器的实例:

 

 

注意:上面截图的实例中,未包含地址位和校验码。

 

0x03和0x06功能码调试

主从机寄存器地址设置不一致

 

 

上面主从机寄存器地址设置不一致的返回:MODSIM32收到的数据包:01 03 00 00 00 06 C5 C8

 

MODSIM32返回的数据包:01 83 02 C0 F1

 

 

主从机寄存器地址一致

 

 

MODSIM32收到的数据包:01 03 00 00 00 06 C5 C8

 

MODSIM32返回的数据包:01 03 0C 01 00 00 00 00 00 00 00 00 00 00 00 6E B3

 

 

主机修改值

使用Modbus功能码0x06:写单路寄存器,实现对从机单个寄存器值的修改。

 

修改地址2的寄存器值为0x00FF

 

 

MODSCAN32发送的数据包:01 06 00 01 00 FF 98 4A

 

MODSIM32返回的应答包:01 06 00 01 00 FF 98 4A

 

主机发送的报文格式:

 

主机发送 字节数 发送的信息
从机地址 1 01
功能码 1 06
起始地址 2 0x0001
写入数据 2 0x00FF
CRC码 2 0x984A

 

 

从机响应返回的报文格式,与主机发送的报文格式及数据内容完全相同。

 

 

修改地址6的寄存器值为0xFF00

 

 

从机修改值

修改地址4的寄存器值为0x0008

 

 

由上我们可以看出来,从机修改完值无需上传数据包(因为Modbus是主从模式,从机不能主动上传数据),等待下次主机查询寄存器状态的时候,上报即可。

 

注意:上面演示使用的ModSim32软件作为从机,MODSCAN32软件作为主机。

 

基于Qt的Modbus从机程序

有了上面的演示,我们知道了主机发送不同功能码的时候,我们应该返回给主机什么样的数据内容,下面我们在之前我们分享的《 使用Qt打造属于自己的串口调试助手 》的基础上,完成0x03和0x06功能码的应答,最终程序的界面显示如下。

 

 

因为Modbus协议是主从模式,从机不会主动发数据包至主机,从机只要解析接收到的数据包,然后根据协议规定返回对应的内容即可。

 

所以我们的Qt程序,主要工作就是解析收到的串口数据,因此,在串口接收函数中,解析收到的数据包具体需要做如下工作:

 

将接收到的前6个字节数据进行CRC计算;

 

CRC计算的结果跟接收到的第7、第8字节比较,如果一致,证明数据包没有问题;

 

如果CRC正确,那么根据接收到的第2字节进行判断,当第2字节为0x03时,为Modbus读寄存器的操作;当第2字节为0x06时,为Modbus写单寄存器的操作;

 

如果功能码为0x03,则获取TableView第2列内的所有数据,作为返回数据包的寄存器值,然后将地址位、功能码、数据长度、寄存器值这些进行CRC校验,然后组成一个数据包发送至主机;

 

如果功能码为0x06,则将收到数据包的数据位组成一个WORD类型的整形数,根据寄存器地址,将其赋值到TableView中对应的单元格中。

 

Qt实现的Modbus从机程序大家可以参考本文提供的源码。

 

总结

经过我们这两次Modbus协议的分享,大家可以试试其他功能码的发送与应答,自己随意玩起吧。