Modebus通信协议 温控器示例

目录

1 指令解释

2 获取动态的CRC

3 crc在线验证

4 16进制正负温度互转

4.2 16进制转温度

4.2 温度转16进制

5 完整工具类


最近安卓工作接了很多硬件,其他的都是发个固定指令,比较有代表性就是温控器和打印机自定义内容所以这个记录接入示例,纯搞安卓或者没有搞过的同学可能还是有点云里雾里,因为很多参数需要自己算,我这里记录一下,有什么疑问留言讨论

1,指令解释

注意协议可能有所不同,但协议思想是差不多 我们以为例

01(从机地址) 03(功能码) 00 00(温度查询) 00 01(寄存个数) 84 0A(校验码 动态)为查询温度举例    

参数(例)含义解释
0x01 从机地址为1基本固定 查厂家文档确认下
0x03 功能码读一个寄存器查询 功能表     
0X0014 起始地址为20 查询地址 20转16进制为14,这里举例20 是为了解释16进制的 
0X0001寄存个数1 基本固定 查厂家文档确认下
0X**CRC16低位CRC根据前面12位生成
0X** CRC16高位CRC根据前面12位生成

    

2,获取动态的CRC

注意这里是说01 03 00 00 00 01生成的84 0A,如果我们写入程序中则需要动态计算,因为前面的参数根据功能不同在变化,所以后面也是变化的,我理解这其实简单理解类似请求参数加密,确保参数没有更改。

傻瓜式使用示例

1.确定 01 03 00 00 ** ** ** ** 地址和功能码

2.再确定 01 03 00 00 00 01 ** ** 转化好的温度

3.再将01 03 00 00 00 01 丢入 getCRC 为 84 0A高低位已经替换到

4.所以查询温度直接输入 01 03 00 00 00 01 84 0A

  /*** 计算CRC16校验码** @param bytes* 字节数组* @return [String] 校验码* @since 1.0*/fun getCRC(bytes: ByteArray): String {// CRC寄存器全为1var CRC = 0x0000ffff// 多项式校验值val POLYNOMIAL = 0x0000a001var i: Intvar j: Inti = 0while (i < bytes.size) {CRC = CRC xor (bytes[i].toInt() and 0x000000ff)j = 0while (j < 8) {if (CRC and 0x00000001 != 0) {CRC = CRC shr 1CRC = CRC xor POLYNOMIAL} else {CRC = CRC shr 1}j++}i++}// 结果转换为16进制var result = Integer.toHexString(CRC).uppercase(Locale.getDefault())if (result.length != 4) {val sb = StringBuffer("0000")result = sb.replace(4 - result.length, 4, result).toString()}//高位在前地位在后//return result.substring(2, 4) + " " + result.substring(0, 2);// 交换高低位,低位在前高位在后return result.substring(2, 4) + " " + result.substring(0, 2)}

3,crc在线验证

CRC(循环冗余校验)在线计算_ip33.com,注意上面的代码已为你交换好了

查询温度

4,16进制正负温度互转

单次温度查询返回结果示例

origin: {"bRec":[1,3,2,0,-26,57,-50],"sComPort":"/dev/ttyS1","sRecTime":"08:47:29"}

Hex: 010302 00E6 39CE

温度Hex: 00E6

温度解析: 23.0 ℃

前后缀去掉拿到数据,返回数据暂时就不验证了直接用,先转16进制再转10进制,因为单位是0.1℃除以10得到℃,但这个温度存在负数,所以咱们还需要解决 温度和进制转化的问题,不仅在查询的时候需要,再设置温度的时候也更需要  反过来所以下面看看互转

4.2 16进制转温度

例 -25.2=0XFF04 25.2=0X00FC -100.0=0XFC18 500.0=0X1388

首先得判断正负数有的地方是根据FF即16进制极值,而我这里根据实际需求判断一个F即可,

然后负数按位取反+1,inv和~取反你们也可以试试 我这里比较直接,不知道是不是版本问题,先这样算,这里的文档厂家标为0.1℃所以还要除以10

      println("hexToTemp FF04:${hexToTempString("FF04")}℃")println("hexToTemp 00FC:${hexToTempString("00FC")}℃")println("hexToTemp FC18:${hexToTempString("FC18")}℃")println("hexToTemp 1388:${hexToTempString("1388")}℃")/*** 16进制带正负转化为10进制*/private fun hexToTempString(hex: String): Float {println("")println("")println("--------------->$hex")// 判断16进制字符串是否为正负val isNegative = hex.uppercase().startsWith("F")// 如果是负数则转为二进制再按位取反再然后得到10进制数值并加上-号return if (isNegative) {val num = hexToIntTemp(hex)// 除10保留两位小数,单位为0.1℃(-num * 100.00f / 1000)} else {val num = hex.toInt(16)(num * 100.00f / 1000)}}/*** 按位取反+1 获取负数问题*/private fun hexToIntTemp(hex: String): Int {// 将 16 进制转换为二进制val binaryString = hex.toInt(16).toString(2)println("binary:$binaryString")// 按位取反val binaryStringInverted = binaryString.map {if (it == '0') '1' else '0'}.joinToString("")println("binaryInverted:$binaryStringInverted")// 两个二进制字符串相加val sum = binaryStringInverted.toInt(2) + 1println("+1:$sum")return sum}

打印结果

4.2 温度转16进制

举例设置温度为1℃

傻瓜式使用示例

1. 01 06 ** ** ** ** ** ** 功能码 06为写入

2. 01 06 00 14 ** ** ** **  地址 为20转化16进制为00 14

3. 01 06 00 14 00 01 1℃转化(看下面)000A

3. 01 06 00 14 00 0A  getCRC获取验证码 49 C9

4.所以查询温度直接输入 01 06 00 14 00 0A 49 C9

如果失败请检查机器是否有最大最小温度限制

分别用tempToHexString方法验证1和2转化16进制,再用上面的方法验证-2的ffec是否正确

  println("tempToTemp 1℃:${tempToHexString("1")}")println("tempToTemp -2℃:${tempToHexString("-2")}")println("验证-2℃ 逆转 ffec:${hexToTempString("ffec")}℃")/*** 整数直接转16进制负数 -1 按位取反*/private fun tempToHexString(num: String): String {println("")println("")println("--------------->$num")val toFloat = num.toFloat()// 将℃转化为0.1℃val toInt = (toFloat* 10).toInt()if (toInt >= 0){// int 转16进制return toInt.toString(16).uppercase().padStart(4, '0')}else{val temp = abs(toInt) -1println("temp-1:${temp}(0.1温度)")// 不足16位进进行0补全val tempBinary = temp.toString(2).padStart(16, '0')println("binary:${tempBinary}")// 按位取反val binaryStringInverted = tempBinary.map {if (it == '0') '1' else '0'}.joinToString("")println("binaryInverted:${binaryStringInverted}")return  binaryStringInverted.toLong(2).toString(16).uppercase()}}

5,完整工具类

package 改为自己的import 改为自己的log your.LogUtils
import java.util.Locale
import kotlin.math.absobject TempUtils {/*** 业务举例 设置温度封装* @param 温度只支持整数(结合实际需求也可以支持小数)*/fun setTemp(temp: String): String {// 功能地址前缀val header = "01 06 00 14"val tempToHexString = tempToHexString(temp)val start = "$header$tempToHexString"LogUtils.log("start:$start")val crc = getCRC(start)LogUtils.log("crc:$crc")val instruct = "$start $crc"LogUtils.log("setTemp:$temp---------------> \ninstruct:$instruct")return instruct}/*** 整数直接转16进制负数 -1 按位取反 单位℃*/private fun tempToHexString(num: String): String {LogUtils.log("")LogUtils.log("")LogUtils.log("--------------->$num")val toFloat = num.toFloat()// 将℃转化为0.1℃val toInt = (toFloat * 10).toInt()if (toInt >= 0) {// int 转16进制return toInt.toString(16).uppercase().padStart(4, '0')} else {val temp = abs(toInt) - 1LogUtils.log("temp-1:${temp}(0.1温度)")// 不足16位进进行0补全val tempBinary = temp.toString(2).padStart(16, '0')LogUtils.log("binary:${tempBinary}")// 按位取反val binaryStringInverted = tempBinary.map {if (it == '0') '1' else '0'}.joinToString("")LogUtils.log("binaryInverted:${binaryStringInverted}")return binaryStringInverted.toLong(2).toString(16).uppercase()}}/*** 16进制带正负转化为10进制*/fun hexToTempString(hex: String): Float {LogUtils.log("")LogUtils.log("")LogUtils.log("--------------->$hex")// 判断16进制字符串是否为正负val isNegative = hex.startsWith("F")// 如果是负数则转为二进制再按位取反再然后得到10进制数值并加上-号return if (isNegative) {val num = hexToIntTemp(hex)(-num * 100.00f / 1000)} else {val num = hex.toInt(16)(num * 100.00f / 1000)}}/*** 按位取反+1 获取负数问题*/fun hexToIntTemp(hex: String): Int {// 将 16 进制转换为二进制val binaryString = hex.toInt(16).toString(2)LogUtils.log("binary:$binaryString")// 按位取反val binaryStringInverted = binaryString.map {if (it == '0') '1' else '0'}.joinToString("")LogUtils.log("binaryInverted:$binaryStringInverted")// 两个二进制字符串相加val sum = binaryStringInverted.toInt(2) + 1LogUtils.log("+1:$sum")return sum}/*** MODBUS协议 CRC16校验码*/fun getCRC(data: String): String {var data = datadata = data.replace(" ", "")val len = data.lengthif (len % 2 != 0) {return "0000"}val num = len / 2val para = ByteArray(num)for (i in 0 until num) {val value = data.substring(i * 2, 2 * (i + 1)).toInt(16)para[i] = value.toByte()}return getCRC(para)}/*** 计算CRC16校验码** @param bytes* 字节数组* @return [String] 校验码* @since 1.0*/fun getCRC(bytes: ByteArray): String {// CRC寄存器全为1var CRC = 0x0000ffff// 多项式校验值val POLYNOMIAL = 0x0000a001var i: Intvar j: Inti = 0while (i < bytes.size) {CRC = CRC xor (bytes[i].toInt() and 0x000000ff)j = 0while (j < 8) {if (CRC and 0x00000001 != 0) {CRC = CRC shr 1CRC = CRC xor POLYNOMIAL} else {CRC = CRC shr 1}j++}i++}// 结果转换为16进制var result = Integer.toHexString(CRC).uppercase(Locale.getDefault())if (result.length != 4) {val sb = StringBuffer("0000")result = sb.replace(4 - result.length, 4, result).toString()}//高位在前地位在后//return result.substring(2, 4) + " " + result.substring(0, 2);// 交换高低位,低位在前高位在后return result.substring(2, 4) + " " + result.substring(0, 2)}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/22681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么没有输出九九乘法表?

下面的程序本来想输出九九乘法表到屏幕上&#xff0c;为什么没有输出呢&#xff1f;怎样修改&#xff1f; <!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>我的HTML练习</title> …

新火种AI|倒反天罡!美国名校斯坦福AI团队抄袭中国大模型

作者&#xff1a;一号 编辑&#xff1a;美美 中国大模型被抄袭&#xff0c;怎么不算是某种层面上的国际认可呢&#xff1f; 5月29日&#xff0c;斯坦福大学的一个AI研究团队发布了一个名为「Llama3V」的模型&#xff0c;号称只要 500 美元就能训练出一个 SOTA 多模态模型&am…

知识库系统:从认识到搭建

在这个信息过载的时代&#xff0c;企业越来越需要一个集中的知识库系统来促进员工协作和解决问题。本文跟着LookLook同学一起来探讨搭建高效知识库系统的所有注意事项和知识库系统的最佳推荐。 | 什么是知识库系统 知识库系统是一种软件或工具&#xff0c;旨在填补组织内的知识…

超越传统AI 新型多智能体系统MESA,探索效率大幅提升

探索多智能体强化学习的协同元探索 —— MESA 算法深度解读在多智能体强化学习&#xff08;MARL&#xff09;的征途中&#xff0c;如何高效探索以发现最优策略一直是研究者们面临的挑战。特别是在稀疏奖励的环境中&#xff0c;这一问题变得更加棘手。《MESA: Cooperative Meta-…

用扫描书籍的功能扫描文档是扫描件吗?

当使用扫描书籍的功能来扫描文档时&#xff0c;产生的结果通常被称为“扫描件”或“扫描图像”。这里的“扫描”一词指的是通过扫描仪或具有扫描功能的设备&#xff08;如一些高端打印机、多功能一体机等&#xff09;将纸质文档转换为数字图像的过程。 扫描件通常是高清晰度的…

关于phpstorm创建类和方法时带描述注释

展示效果&#xff1a; 1、使用phpstorm创建类文件时自带注释及注释编辑 步骤1&#xff1a; 步骤二&#xff1a; 内容&#xff1a; <?php /** * Desc: * author guowei * datetime $DATE $TIME */ #if (${NAMESPACE}) namespace ${NAMESPACE}; #end class ${NAM…

计算机网络 —— 数据链路层(以太网)

计算机网络 —— 数据链路层&#xff08;以太网&#xff09; 什么是以太网以太网传输介质和拓扑结构的发展传输介质的发展&#xff1a;拓扑结构的发展&#xff1a; 10BASE-T 以太网适配器和MAC地址适配器&#xff08;Adapter&#xff09;MAC地址适配器与MAC地址的关系 MAC帧以太…

使用Java进行网络采集:代理IP与参数传递详解

在Java编程语言中&#xff0c;参数传递机制是一个常见的讨论话题。理解这一点对于编写高效且无错误的Java代码至关重要。本文将探讨Java的参数传递机制&#xff0c;解析其究竟是“按引用传递”还是“按值传递”&#xff0c;并结合网络爬虫技术的实例&#xff0c;展示如何在实际…

【机器学习】机器学习与推荐系统在电子商务中的融合应用与性能优化新探索

文章目录 引言机器学习与推荐系统的基本概念机器学习概述监督学习无监督学习强化学习 推荐系统概述基于内容的推荐协同过滤混合推荐 机器学习与推荐系统的融合应用用户行为分析数据预处理特征工程 模型训练与评估模型训练模型评估 个性化推荐基于用户的协同过滤基于商品的协同过…

【Git教程】(二十)外包长历史记录 — 概述及使用要求,执行过程及其实现,替代解决方案 ~

Git教程 外包长历史记录 1️⃣ 概述2️⃣ 使用要求3️⃣ 执行过程及其实现3.1 外包项目历史3.2 链接到当前活动版本库 Git 版本库会随着时间积累越来越大&#xff0c;会影响它的内存管理效率。通常在版本库中只有源 代码文件情况下&#xff0c;这点效率影响可以忽略不计。在现…

WSDM 2023 推荐系统相关论文整理(三)

WSDM 2023的论文录用结果已出&#xff0c;推荐系统相关的论文方向包含序列推荐&#xff0c;点击率估计等领域&#xff0c;涵盖图学习&#xff0c;对比学习&#xff0c;因果推断&#xff0c;知识蒸馏等技术&#xff0c;累计包含近四十篇论文&#xff0c;下文列举了部分论文的标题…

Stable Diffusion【应用篇】【图片修复】:模糊头像照片的高清修复

本文主要是回复一下后台小伙伴留言的问题。经小伙伴本人同意后&#xff0c;允许使用待修复的照片。 我们先看一下待修复的照片。 在向我咨询之前&#xff0c;小伙伴也自己进行了尝试&#xff0c;如果直接使用Stable Diffusion的后期处理功能&#xff0c;出来的图片效果是这样的…

GPEN——使用GANs恢复对人脸图像进行修复

1. 简介 盲目的面部修复&#xff08;Blind Face Restoration, BFR&#xff09;是一个活跃的研究领域&#xff0c;它涉及到在没有任何先验信息的情况下改善低质量&#xff08;Low Quality, LQ&#xff09;图像的质量。这确实是一个具有挑战性的问题&#xff0c;因为模型需要能够…

3分钟学会短信群发-在线云短信平台发送教程

在线云短信平台发送教程 这是一个简单的短信平台的电脑在线发送教程&#xff0c;快速上手三分钟搞定&#xff0c;欢迎讨论分享&#xff1a; 1.登录短信平台 找一个资质齐全的在线云短信平台&#xff0c;以赛邮为例&#xff0c;注册认证后创建短信模版。 2.创建短信模版 输入编辑…

在加拿大寻求2亿美元融资!Xanadu的CEO有话要说

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨慕一/娴睿 排版丨沛贤 深度好文&#xff1a;1500字丨5分钟阅读 摘要&#xff1a;加拿大光量子计算头部企业Xanadu希望在加拿大筹集1-2亿美元&#xff0c;用于建立量子数据中心。虽然融资不…

期刊的分类与级别

在学术界&#xff0c;期刊的分类与级别构成了一个评价学术成果和学者贡献的重要标准&#xff0c;同时也是学术出版与学术交流的基础。然而&#xff0c;对于初涉学者来说&#xff0c;理解期刊的分类与级别可能并不直观。本文旨在提供一个系统性的解释&#xff0c;并阐述为何期刊…

【优选算法】字符串

一、相关编程题 1.1 最长公共前缀 题目链接 14. 最长公共前缀 - 力扣&#xff08;LeetCode&#xff09; 题目描述 算法原理 编写代码 // 解法一&#xff1a;两两比较 class Solution { public:string longestCommonPrefix(vector<string>& strs) {int k strs[0…

AI烟火识别算法在消防安全与火灾预警系统中的应用与价值

在信息化和智能化的今天&#xff0c;烟火识别算法作为一种重要的技术工具&#xff0c;在火灾预防和处理中发挥着关键作用。其工作原理主要基于深度学习和图像处理技术&#xff0c;能够实时分析监控画面&#xff0c;准确检测出图像中的烟火&#xff0c;并发出预警。 一、烟火识…

多功能光时域反射仪的工作原理

6426A-2101多功能光时域反射仪是新一代掌上型智能化光纤通信测量仪器&#xff0c;具有强大的功能和广泛的应用领域。它能够显示光纤及光缆的损耗分布曲线图&#xff0c;测量光纤及光缆的多种关键参数&#xff0c;包括长度、损耗、接续质量等&#xff0c;为光纤通信系统的工程施…

ubuntu20.04设置文件开机自启动

硬件&#xff1a;树霉派4B 系统&#xff1a;ubuntu20.04 在ubuntu20.04上经常需要运行 ./BluetoothServerParse_L.c ,比较繁琐&#xff0c;想要设置开机自启动&#xff0c;让树霉派4B在接上电源之后就自动运行该程序。使用systemd服务&#xff0c;设置步骤如下&#xff1a; &…