• 关于freemodbus协议中eMBFuncReadHoldingRegister()函数的所谓错误


    摘要:网上看到有好心的网友提示,freemodbus协议中的mbfuncholding.c 文件中eMBFuncReadHoldingRegister()函数,有一处错误,即:第185行的“usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );”应为“usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );”,我认为这不能算是一个错误,且听我的分析。

    关键词:freemodbus Modbus 保持寄存器 eMBFuncReadHoldingRegister

    1.关于freemodbus协议栈的一点粗浅体会

    Modbus通信协议,搞过工业控制的人,多多少少应该了解一点。其结构简单,应用广泛。几乎是很多PLC的标配接口。但其通信规约也有几十页之多,要在单片机上实现,如果自己写源代码,估计还是需要一些时间的,因为不光要实现常用的功能,还要保持协议的完整性和错误处理机制。

    freemodbus是一个比较完整的协议栈,有机构在维护,并且开源。有点单片机基础得朋友,1个小时应该可以移植好(前提能参考一个不错的教程)。比自己撸代码快N倍。个人感觉这个协议栈还是很好用的,但免费的只支持从站,需要做主站就要自己再想办法了。

    2.为什么说这不算个错误

    首先要看这句代码是干什么用的?上下文如下:

    usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 );

    usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] );

    usRegAddress++;

    usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8 );

    usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );

    pucFrame[MB_PDU_FUNC_READ_ADDR_OFF]存储的是Modbus数据帧中寄存器起始地址的高字节,pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] 存储的是Modbus数据帧中寄存器起始地址的低字节,pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] 存储的是Modbus数据帧中寄存器个数的高字节,pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] 存储的是Modbus数据帧中寄存器个数的低字节。

    下面给一个实例,能更好理解,如图1。此帧数据是读取地址为1的从站的保持寄存器,寄存器起始地址为:18430(0x47FE),读取寄存器的个数为:101(0x0065),在这里:

    pucFrame[MB_PDU_FUNC_READ_ADDR_OFF]的值为:0x47;

    pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] 的值为:0xFE;

    pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] 的值为:0x00;

    pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] 的值为:0x65。

    从这里也可以看出,Modbus在发送一个word(16bit)数据的时候,是高字节在前,低字节在后。

    图1

    既然pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] 表示的是寄存器个数的高字节,那么我们来查看一下Modbus协议,看一下这个参数的范围,如图2、图3所示。此两图是从Modbus协议文本中截出来的,0x03功能码是读保持寄存器,0x10功能码是写多个保持寄存器,这两个功能码会涉及到保持寄存器数量的问题,寄存器数量的范围一个是0x7D,一个是0x78,都在一个字节的范围内,因此,寄存器数量这个参数的高字节始终为0,也就是说pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF]是等于0的,可以不处理。

    图2

    图3

    3.总结及讨论

    综上,我认为这个不能算是个错误,不影响程序的正常结果,只是写法不够严谨。但有一个极端情况,是有影响的,Modbus主站读写寄存器的数量超过协议规定的数量的时候,本应该返回错误码,但这种写法由于只处理了低字节,就有可能认为没有错误,而对数据进行处理。为了安全起见,大家还是把这句代码改掉吧,改为“usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1] );”,以防止极端情况的发生。

    还有一个问题,Modbus协议规定的读写保持寄存器的数量都在一个字节的范围内,发送数据的时候为什么要用2个字节来表示寄存器数量,这个还没有做深入研究,可能是考虑协议的整体兼容性吧,有兴趣的朋友可以一起讨论。

  • 相关阅读:
    【C语言】23typedef
    C#蓝牙开发之查找设备以及配对
    GridView获取隐藏列的值
    PDA(Windows Mobile)调用远程WebService
    VS2008使用宏记录来实现自动增加注释信息
    CS 系统框架二[部分内容更新]
    GridView里面嵌套RadioButton
    .Net 以报表的形式加载SAP里面的数据
    取GridView的PagerTemplate里面的控件ID
    《深入Ajax架构和最佳实践》读书笔记
  • 原文地址:https://www.cnblogs.com/kongbh/p/13789319.html
Copyright © 2020-2023  润新知