摘要:网上看到有好心的网友提示,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个字节来表示寄存器数量,这个还没有做深入研究,可能是考虑协议的整体兼容性吧,有兴趣的朋友可以一起讨论。 |
|