加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 实现目标
    • 结果展示
    • 素材获取
    • 读保持寄存器功能码0x03
    • 写单个寄存器功能码0x06
    •  
    • 写多个保持寄存器功能码0x10
    • 0x03和0x06功能码调试
    • 基于Qt的Modbus从机程序
    • 总结
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

Qt编写Modbus从机程序

2021/03/22
430
阅读需 6 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

上一个网文我们使用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协议的分享,大家可以试试其他功能码的发送与应答,自己随意玩起吧。

相关推荐

电子产业图谱

公众号『嵌入式从0到1』,号主:程序员小哈,是一个软硬件全栈开发工程师(12年工作经验的老司机),电子发烧友论坛鸿蒙版块版主,公众号内容专注于嵌入式学习。坚持原创,写有图、有视频的保姆级教程文章,篇篇有干货。做一个讲清楚,说明白,大家学得会的交流平台。