Modbus RTU 解析接收到的byte[] 数组该如何解析成十进制数?

Tidal_Choidi 2018-04-24 09:36:00
串口RS485Modbus 通讯协议,下行数据帧是功能码为3的读从站的保持寄存器。读两个寄存器地址,从站返回四个字节的数据。


问题:接收到缓冲区是包含了4个byte类型的十进制数据,如:00,00,18,64.请问,可以通过什么办法将左边的四个byte类型的数据拼接成一个十进制数据? 我尝试着用 BitConvert.toInt(recBuffer,0)这个方法进行转换,实际转换出来的结果不对。上面的四个数据实际上已经是十进制的数了,能不能有一种办法把上面的四个byte类型数据拼接成一个十进制数?
...全文
1705 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
lwqwag 2018-04-25
  • 打赏
  • 举报
回复
高低位互换应该就可以了
xuzuning 2018-04-25
  • 打赏
  • 举报
回复
            var b = new byte[] { 00, 00, 18, 64 }; //大端序
            var n = BitConverter.ToInt32(b, 0);//直接转换
            Console.WriteLine(n);//1074921472 结果不对 
            Console.WriteLine(BitConverter.ToInt32(b.Reverse().ToArray(), 0));//转置后转换 4672
            Console.WriteLine(System.Net.IPAddress.NetworkToHostOrder(n));//网络转本地 4672
            Console.WriteLine((((b[0] * 256) + b[1]) * 256 + b[2]) * 256 + b[3]); //验算 4672
具体情况要具体分析。显然你是不会一次只收到这4个字节的 用连续的 BitConvert.toInt(recBuffer,offs) 读取出所有的整形数后,再转成本地的比较稳妥
zmyouren1983 2018-04-25
  • 打赏
  • 举报
回复
Array.Reverse(recBuffer) 转一下再调BitConverter.ToUInt16
秋的红果实 2018-04-25
  • 打赏
  • 举报
回复
据我所知,RTU模式下,是16进制数,以二进制串方式传输的 能不能有一种办法把上面的四个byte类型数据拼接成一个十进制数? ==> 需要说出拼接的方式
xuzuning 2018-04-25
  • 打赏
  • 举报
回复
c#直接提供了网络字节序转换方法。 System.Net.IPAddress.HostToNetworkOrder(本机到网络转换) System.Net.IPAddress.NetworkToHostOrder(网络字节转成本机)
toto0805 2018-04-25
  • 打赏
  • 举报
回复
C#要先将字符转成无符号短整。然后把高低位调换后赋值给一个32位的int
toto0805 2018-04-25
  • 打赏
  • 举报
回复
在C里搞过 rbuf是接受的字节;四个ziyji int mdbadr=0,LoHex=0,HiHex=0;//寄存器起始地址,地址高位,地址地位 int mdbqty=0,qLoHex=0,qHiHex=0;//寄存器数量,寄存器数量地位,寄存数量器高位 LoHex=rbuf[3] ; HiHex=rbuf[2] ; mdbradr=HiHex<<8|LoHex;//寄存器起始地址的高位低位合并 qLoHex=rbuf[5] ; qHiHex=rbuf[4] ; mdbqty=qHiHex<<8|qLoHex;//寄存器数量的高位低位合并
xuzuning 2018-04-24
  • 打赏
  • 举报
回复
计算机里多是低位在前,通讯中多是高位在前
【资源说明】 基于stm32的uart串口modbus通讯协议源码+说明文档.zip modbus-RTU协议 **Modbus报文帧结构** 一个报文就是一帧据,一个据帧就一个报文: 指的是一串完整的指令据,本质就是一串Modbus协议在串行链路上的报文格式如下所示: ![image](https://github.com/KeyL-SJ/stm32_uart_modbus/assets/78483846/bcec2fe4-3a28-42b3-b2aa-8d75f8fe1f36) | 从机地址 | 功能码 | 据 | CRC校验 | | :------: | :----: | :-----: | :-----: | | 1 byte | 1 byte | N bytes | 2 bytes | **帧结构 = 从机地址 + 功能吗 + 据 + 校验** - 从机地址: 每个从机都有唯一地址,占用一个字节,范围0-255,其中有效范围是1-247,其中255是广播地址(广播就是对所有从机发送应答) - 功能码: 占用一个字节,功能码的意义就是,知道这个指令是干啥的,比如你可以查询从机的据,也可以修改从机的据,所以不同功能码对应不同功能. - 据: 根据功能码不同,有不同功能,比方说功能码是查询从机的据,这里就是查询据的地址和查询字节等。 - 校验: 在据传输过程中可能据会发生错误,CRC检验检测接收据是否正确 # Modbus功能码 **Modbus规定了多个功能,那么为了方便的使用这些功能,我们给每个功能都设定一个功能码,也就是指代码。** Modbus协议同时规定了二十几种功能码,但是常用的只有8种,用于对存储区的读写,如下表所示: | 功能码 | 功能说明 | | :----: | :------------: | | 01H | 读取输出线圈 | | 02H | 读取输入线圈 | | 03H | 读取保持寄存器 | | 04H | 读取输入寄存器 | | 05H | 写入单线圈 | | 06H | 写入单寄存器 | | 0FH | 写入多线圈 | | 10H | 写入多寄存器 | 当然我们用的最多的就是03和06 一个是读取据,一个是修改据。 # CRC校验 **错误校验(CRC)域占用两个字节包含了一个16位的二进制值。CRC值由传输设备计算出来,然后附加到据帧上,接收设备在接收据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不相等,就发生了错误。** 例如若主机向从机发送报文`01 03 00 00 00 01 84 0A` 其中, 最后两个字节`84 0A`就是CRC校验位,从机接收到主机发送的报文之后,根据报文的非校验位`01 03 00 00 00 01`计算CRC校验位,若从机计算出的校验位与主机发送的校验位相同,则证明据在发送的过程中没有发生错误,反之,则代表据传输发生错误。 ## CRC校验流程 1、预置一个16位寄存器为`0FFFFH`(全1),称之为CRC寄存器。 2 、把据帧中的第一个字节的8位与CRC寄存器中的低字节进行异或运算,结果存回CRC寄存器。 3、将CRC寄存器向右移一位,最高位填以0,最低位移出并检测。 4 、如果最低位为0:重复第三步(下一次移位);如果最低位为1:将CRC寄存器与一个预设的固定值`0A001H`进行异或运算。 5、重复第三步和第四步直到8次移位。这样处理完了一个完整的八位。 6 、重复第2步到第5步来处理下一个八位,直到所有的字节处理结束。 7、最终CRC寄存器的值就是CRC的值。 【备注】 1、该资源内项目代码都经过测试运行功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧