MODBUS报文负数优化处理代码(补码,反码) java

  • 前言
    • 写此文档的原因
    • 参考资料
    • 简洁代码实现方式
    • 实现代码
      • 核心转码代码
      • 转换的工具类:
      • 结束

前言

写此文档的原因

今天弄MDOBUS报文处理,因为以前弄个,但处理数据时用了各种 If 和 for,代码极度不简洁也不高效,所以单独查询更简洁更高效的处理方法,但各种资料中,解决原理和解决方式都有,但具体代码描述和实际操作并没有说明,所以单独记录了此文档。

参考资料

以下文章需取重点同步观看,每个都只讲了部分内容
代码中所使用的运算符及原因: 点击查看原帖.
为什么转换会这么麻烦及原因: 点击查看原帖.
原码、反码、补码和符号介绍: 点击查看原帖.

简洁代码实现方式

代码想简洁高效,首先就要理清操作原因:

  1. 在MODBUS中,正数取值和负数取值是不一样的;
  2. 如果直接把负数当成正数转码进行数据转换,转换时会把符号位当数据进行了转换;
  3. MODBUS报文分为状态位(简单理解为false和true)和数据位数据;
  4. MODBUS数据位分为数值和字符(ACISS),数值又分为正数和小数,此处不讨论小数
  5. MODBUS一个字节(byte)只能保存0~255(也可以说是-128到127)的数字
  6. 当数值超过一个byte时,需继续增加byte传递数据,此时需区分高位和低位(可以简单理解为高位值为2时代表两个满值低位)
  7. 有部分厂家,高位和低位具体是哪个不一定,有的前面是高位,有的后面是高位,需确认区分

实现代码

实现的代码分两部分,一个是简洁的,少的关键转码(主要是负数),还有一个是地城的byte工具类,但是我不需要使用它的jar包,所以把方法抽了出来成为工具类使用

核心转码代码

此代码为转码核心,先区分正负值在根据符号去处理

/*** MODBUS转码* (不支持小数转码)** @param byte1 待转码数据(高位)* @param byte2 待转码数据(低位)*/public Double byteToInt(byte byte1,byte byte2){//高位在前,低位在后//byte[] bs1 = new byte[]{(byte) 0xFF,(byte) 0x3D};       //测试数据:负数    -195//byte[] bs1 = new byte[]{(byte) 0x00,(byte) 0xC3};       //测试数据:正数    195int number = 0;//1、取出高位符号if(byte1<0){//负数先高位左移8位和低位拼接,再取反number =~(byte1<<8 | byte2);//补码并赋值符号位number =-(number+1);}else{//正数直接转成16位字符(主要为拼接字符串)String s = XmByteUtils.toHexAscii(new byte[]{byte1,byte2});//直接把16进制字符转intnumber = Integer.parseInt(s, 16);}//把已取出的数据做额外处理return (double) number / 10;        //具体数据处理}

代码解析:
原始数据转换例子(数值随便写的,仅是案例):
byte1:10000101
byte2:00011101

转换解释及案例
byte1<<8:把高位数据左移8位,给低位数据合并留出空间 (例:10000101 00000000)
byte1<<8|byte2:把高位数据和低位数据合并(例:10000101 00011101)
~(byte1<<8 | byte2):反码:(例:01111010 11100010)
-(number+1):补码就是加一,因为符号位丢失,再给他加上(例:11111010 11100011)

转换的工具类:

具体干什么就不细讲了,我也是把底层原码考出的,当做工具类使用

package com.system.xiaoma.util;import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;public class XmByteUtils {/*** MODBUS报文字符串(不带空格)转 byte可发送的HEX格式* @param s MODBUS报文字符串*/public static byte[] fromHexAscii(String s) throws NumberFormatException {try {int len = s.length();if ((len % 2) != 0)throw new NumberFormatException("Hex ascii must be exactly two digits per byte.");int out_len = len / 2;byte[] out = new byte[out_len];int i = 0;StringReader sr = new StringReader(s);while (i < out_len) {int val = (16 * fromHexDigit(sr.read())) + fromHexDigit(sr.read());out[i++] = (byte) val;}return out;} catch (IOException e) {throw new InternalError("IOException reading from StringReader?!?!");}}/**** @param c 需发送命令的16位数值转换* @return* @throws NumberFormatException*/private static int fromHexDigit(int c) throws NumberFormatException {if (c >= 0x30 && c < 0x3A)return c - 0x30;else if (c >= 0x41 && c < 0x47)return c - 0x37;else if (c >= 0x61 && c < 0x67)return c - 0x57;elsethrow new NumberFormatException('\'' + c + "' is not a valid hexadecimal digit.");}/*** byte数组转十六位字符串(不带空格)* @param bytes 待转换的byte数组*/public static String toHexAscii(byte[] bytes) {int len = bytes.length;StringWriter sw = new StringWriter(len * 2);for (int i = 0; i < len; ++i)addHexAscii(bytes[i], sw);return sw.toString();}/*** byte转16位并拼接* @param b     数组* @param sw    字符串*/static void addHexAscii(byte b, StringWriter sw) {int ub = unsignedPromote(b);int h1 = ub / 16;int h2 = ub % 16;sw.write(toHexDigit(h1));sw.write(toHexDigit(h2));}/*** byte取补位数据* @param b 数组* @return*/public static int unsignedPromote(byte b) {return b & 0xff;}/* note: we do no arg. checking, because     *//* we only ever call this from addHexAscii() *//* above, and we are sure the args are okay  */private static char toHexDigit(int h) {char out;if (h <= 9) out = (char) (h + 0x30);else out = (char) (h + 0x37);//System.err.println(h + ": " + out);return out;}
}

结束

如果上面代码有BUG或更方便的写法请在评论告知,我会及时更新的,后续使用中我也会根据使用情况更新代码,谢谢!

晋级处理方式来啦:点击查看新内容

MODBUS报文负数优化处理代码(补码,反码) java相关推荐

  1. C正数负数的原码补码反码以及内存地址分析

    #include<stdio.h> void swap(int a, int b); void main1(){int i = 10; //正数的原码 00000000 00000000 ...

  2. 正数/负数的原码、反码、补码

    1.正数的原码.反码.补码相同(三码合一). 例如:14转换为二进制 0000 1110 其中:从左到右看,第一位是符号位. 符号位为 0 表示正数 符号位为 1 表示负数 2.负数的原码.反码.补码 ...

  3. 正数、负数求原码、反码、补码

    二进制,有符号数,首位为1的是负数,首位为0的是正数.(规定) 无符号数没有正负之分,所以也没有首位的限制.(规定) (以下示例皆以八位二进制表示) 无符号数 无符号数的原码.反码.补码都一样,皆为该 ...

  4. java反码补码原码作用_java原码补码反码关系解析

    本文为大家解析了java原码补码反码的关系,供大家参考,具体内容如下 原码:不管源数据是十进制还是十六进制,统统将数字转成二进制形式 反码:把原码的二进制统统反过来,0变成1,1变成0 补码:负数的反 ...

  5. 原码补码反码概括简介

    原码介绍 原码就是符号位加上值的绝对值,第一位数字表示符号,其余位表示值 10 原码:0000 0000 0000 0000 0000 0000 0000 1010 -10 原码:1000 0000 ...

  6. java通信rs485_基于VB6.0与485仪表的Modbus RTU通信(含代码)

    JZGKCHINA工控技术分享平台 尊重原创 勿抄袭 勿私放其他平台 前言 在写这边文章时,很纠结,到底要不要写呢?原因主要有3个:第一.VB6.0这么古老的语言现在还有人用吗?现在不是很流行C#.P ...

  7. 16位二进制补码 c语言,2,16进制原码补码反码问题

    1. 在计算机里,通常用数字后面紧跟一个英文字母来表示该数的数字, 十进制一般用D,二进制用B,八进制用O,十六进用H来表示, 2. 首先,十进制数转换成二进制,除2取余,按箭头方向写,自上而下写出来 ...

  8. 前端性能优化常用代码

    前端性能优化常用代码 为什么要做性能优化?性能优化到底有多重要? 网站的性能优化对于用户的留存率.转化率有很大的影响,所以对于前端开发来说性能优化能力也是重要的考察点. 性能优化的点非常的多,有的小伙 ...

  9. 真值 原码 补码 反码 移码

    真值 原码 补码 反码 移码 真值是相对与其它四种的数字类型 书写中一般表示的数叫做"真值" 机器中编码表示的数 "机器数||机器码<原码 补码 反码 移码 > ...

最新文章

  1. 数据资源丨开放中的行政大数据——国内篇(附链接)
  2. 【Elastic Stack学习】ELK日志分析平台(一)ELK简介、ElasticSearch集群
  3. 揭秘:美国国防部用什么样的操作系统
  4. mxnet统计运算量
  5. 微博收藏(机器学习课程与论文)(三)
  6. 【计算机本科补全计划】Mysql 学习小计(2)
  7. 技术实践 | Web 端实现 RTC 视频特效的解决方案
  8. go gin路由分组route group
  9. 【操作】Json取value时,为什么得到的是undefined?
  10. 荒岛求生游戏显示服务器不行,《荒岛求生》黑屏解决方法
  11. h5的formData 上传文件及.net后台
  12. mailto 附带附件_我和我的朋友如何将附带项目发展为每月$ 17,000的业务
  13. matlab概率及数理统计学习-T检验、卡方检验、直方图分布检验
  14. 3dsmax学校教室模型_从小学教室到大学教室的开放项目合作
  15. 装饰效果(最大连续字段和)
  16. 容器的六大误区和八大正确场景(颠覆你的认知)
  17. 数据之路 - Python爬虫 - 正则表达式
  18. poj[2230]Watchcow 深搜 欧拉回路
  19. Blockchain Meets Edge Computing: A Distributed and Trusted Authentication System
  20. 初识动态规划(一)简单入门动态规划与上手操作

热门文章

  1. [渝粤教育] 西南科技大学 电子信息工程专业导论 在线考试复习资料
  2. 打包时出现No matching provisioning profile found错误的解决方法
  3. 北京的房租到底有多高?
  4. 【python】计算机视觉~舌象图片中舌体倾斜判别(四)
  5. 钛媒体2022 EDGE AWARDS全球创新评选之「年度最佳企业服务品牌」揭榜
  6. eplan p8详细安装步骤文库_EPLAN P8 2.1.6 安装指南
  7. 【自然语言处理与文本分析】自然语言处理概要
  8. 像素生存者2服务器无响应,像素生存者2闪退掉线黑屏怎么办?如何解决
  9. 为什么需要重写 equals方法?
  10. 技巧/诀窍:用 .NET 3.5 创建 ToJSON() 扩展方法 (木野狐译)