zoukankan      html  css  js  c++  java
  • 外行小白的modbus惊心之旅

    外行小白的modbus惊心之旅

            这是一个悲伤的故事,笔者自真正接触编程后,学习的一直是编写javaweb项目,然而万万没想到的是,有生之年竟然会接触到串口通信的需求。为了能够帮助到一些和我面临着相同困境的小伙伴们,特此将自己这一段时间来的心得体会记录下来,希望能给大家带来一点点的助益,本文新手向,大佬请绕行~

    (注意:由于笔者对于这方面也是外行,所以文章中可能有些术语不当、思路不佳之处,大家见谅!)

    我接到的需求大致如下:

    现有温湿度监控设备N台,需要编写一个软件,部署在用户的电脑上,通过com口对温湿度设备进行数据采集,并将采集到的数据解析后传送给平台。

           网上不难找到关于如何采集数据的代码,所以在本文中就不再赘述了,那么接下来我们就聊一下,采集到数据之后,如何解析成用户想要的数据。假设你现在得到了设备返回的一条完整数据,这条数据是以字节数组的形式存储的,示例如下:

    byte数组:[01 09 00 01 01 05 49 DB]

    数组下标:[0   1   2   3   4   5   6    7]

    下标0:设备地址号      下标1:命令号(假设09为采集数据命令)      下标2和下标3:存储器号      下标4和下标5:温度数据      下标6和下标7:校验码

    那么问题来了,byte的取值范围为-128~127,难道室内温度还能达到-128或者127不成?为什么存储温度数据要用两字节呢?

           因为一个字节占8位,而设备返回的温度数值是一个16位的整数,所以需要用两个字节来存储。比如现在室内温度为25.5摄氏度,那么设备将会返回给我255。由于我使用的是c#语言,在c#中byte是无符号的,取值范围为0~255,那么我最终采集到的数据以十进制的形式打印出来就是  0  255。那么,为什么第一个字节是0,第二个字节是255呢?

           255的二进制形式为11111111,如果保存为16位,则应该为0000 0000 1111 1111。由此可见,高八位为8个0,低八位为8个1。而一个字节为八位,所以,高八位存在了第一个字节,它的十进制也就是0,而低八位存在了第二个字节,它的十进制为255。由于我使用的是c#语言,所以,最终看到的结果为  0  255。起初的时候,我没有意识到最本质的问题,计算机存储的实际上是二进制数,所以导致了我以一种奇怪的思路来对数据进行解析,而当踩坑之后,经过不断的查阅资料和询问厂家之后,终于总结出了三个关键字:高八位、低八位、十六位整数。

    进而我想到了位运算,将高八位先转为16位进行存储,然后左移八位,低位补零。那么示例中的高八位应该变成了这个样子:0000 0000 0000 0000。

    然后将高八位与低八位相加:

    0000 0000 0000 0000

                       1111 1111

    最终得到的结果为:0000 0000 1111 1111,转为十进制也就是255。

    //代码供参考
    ((Convert.ToInt16(b[5])) << 8) + b[6]

    接下来,再来聊一下我在 这个需求之中遇到的其他坑... ...

    粘包和分包问题:

    最开始在网上查询资料的时候,就读到了这两个词,当时还抱着一点侥幸心理,暗自思量着这东西说不定是什么高端操作吧?我这需求里应该用不到吧?

    结果后来在数据采集的时候,问题就出现了,时而可以采集到数据,时而采集不到数据。我当时的确是百思不得其解,既然能接收到数据,那我的代码应该没什么问题吧?但为什么有时候又接收不到数据呢?

    后来下载一个串口监测工具才发现了问题所在,比如一条完整数据应该为8字节,但是,我接到的数据中,有时是一次性接收到8字节的数据,有时则是先接收了三字节,然后接收了五字节。

    另外一种情况就是,有时还会一次性接收到十几字节的数据,当时一度怀疑是某些转接设备的问题,经过仔细观察发现,原来在这条数据中,有一部分是第一条数据,另一部分是第二条数据。

    解决方案:

    采用生产者和消费者的方式来解决,生产者采集数据存入缓存队列,消费者每当从队列中取出八个字节,进行一次校验,校验成功后,再对数据进行解析和转发。

  • 相关阅读:
    使用SpringBoot校验客户端传来的数据
    在RestController中获取各种信息的方法
    SpringBoot的文件上传&下载
    Maximum upload size exceede上传文件大小超出解决
    在SpringBoot程序中记录日志
    使用IDEA配置SpringBoot热部署无效解决
    RESTful API是什么?
    IDEA如何配置jdk路径
    使用IDEA集成Spring框架时右下角警戒
    Spring框架各模块功能介绍
  • 原文地址:https://www.cnblogs.com/wxdmw/p/13246456.html
Copyright © 2011-2022 走看看