关键词:
背景
做上位机开发时,上位机和下位机如何进行通讯,一般取决于下位机。有这样一个通信协议:
- 当上位机给下位机发送 19 02 01 时,代表读故障码
- 当下位机响应 59 02 01 DD 时,代表肯定响应,其中 DD 代表故障码
- 故障码用4个字节表示
- 每一帧数据为8个字节
- 当无故障码或仅有一个故障码时,一个数据帧8个字节就够了
- 当无故障码或仅有一个故障码时,第一个字节代表有效字节数据长度
例如:03 59 02 01 FF FF FF FF 这一帧,03代表有效字节数据长度,其中有效字节数据为 59 02 01 - 当有多个故障码时,首帧的第二个字节代表有效字节数据长度,第一个字节10标识该数据帧为首帧
- 当有多个故障码时,从首帧第二个字节可得知有多少个有效字节数据长度,例如十六进制的 0B 代表 11 个有效字节数据长度
- 当有多个数据帧时,需要发送 30 00 14 来请求 连续帧
- 当发送 30 00 14 时,下位机响应连续帧,如:21 09 84 02 05 09 FF FF ,其中 21 表示第一个连续帧(在仅有两个数据帧的情况下,第一个连续帧,代表第二帧数据)
那么问题来了,当上位机给下位机发送 19 02 01 读故障码时,如何读出所有故障码呢?换句话说,在有多个故障码的前提下,如何根据首帧的第二个字节,来计算有多少个数据帧或者连续帧呢?
注意:之所以要计算有多少个数据帧或连续帧,是因为要根据这些帧,来循环请求接下来要响应的数据,从而得到完整的故障码数据
协议补充说明
描述的有点晦涩难懂,我举个例子,当设备有两个故障码时(注意这里已经告诉你有多个了,实际情况下,需要我们计算,应该有多少个故障码和数据帧):
- 上位机给下位机发送:03 19 02 01 FF FF FF FF 读故障码
- 下位机响应的数据帧:10 0B 59 02 01 83 02 05,由该数据帧的第一和第二个字节可知,需要多个数据帧来响应故障码,其中有效字节数据长度为 0B ,即 11 个有效字节长度
- 上位机给下位机发送:30 00 14 FF FF FF FF FF 请求第一个连续帧(在这个例子里总共就两帧数据)
- 下位机响应的数据帧:21 09 84 02 05 09 FF FF,(因为这个例子里,总共就两个故障码,需要占用8个字节,所以这里是第一个连续帧,也就是第二帧数据,也是最后帧数据)
我们根据协议来观察,下位机响应的首帧数据 10 0B 59 02 01 83 02 05
中,10 代表首帧标识,0B 代表有效字节数据长度,也就是十进制的 11,这里的有效字节数据长度指的是:59 02 01 83 02 05 09 84 02 05 09 。
注意:第一个连续帧(也就是第二帧,也是最后一帧)的第一个字节,不算做有效字节数据,它算作连续帧的标识,21 代表第一个连续帧,假如是 22 则代表第二个连续帧,以此类推。
那么我们得知了有效字节数据是:59 02 01 83 02 05 09 84 02 05 09 ,根据协议,一个故障码4个字节,除去开头的肯定响应 59 02 01 外,那么第一个故障码为 83 02 05 09 ,第二个故障码为 84 02 05 09 。
如何用代码求解
根据上述的举例说明,应该对上位机下位机通讯的协议,有了一定的了解,在此基础上,请你求出有多少个数据帧或连续帧,并且求出有多少个故障码,每个故障码是什么,以及如何用代码解决这些问题?
尝试穷举寻找规律
我试图尝试用穷举法来找寻规律以解决该问题,假设我们罗列处十个数据帧的数据,如下:
假设当有2个故障码的情况下,我数了一下共有11个有效字节长度,实际响应的字节则有14个,此时需要两个数据帧来传输,以此类推。
我苦思冥想,但似乎没有规律可循?看到这里你是否有了答案?别着急先想想,再往下看。
经人指点得到良方
这样一个小问题,竟然困扰我将近两个小时之久,实在寻不到答案,遂找他人寻求帮助。经过高人指点,我发现我似乎遗漏了一个重要的问题,那就是:在有多帧数据的情况下,首帧数据的有效字节长度为 6(除去首帧的第1、2个字节,还剩下6个字节)。
还有重要的一点,我似乎在通过寻找规律,来求出所有的数据帧,这一点思路不太正确。实际上,我只需要求出有多少个连续帧就可以了,因为有多少个连续帧,才真正是我要循环发送请求连续帧的次数!!
那么答案就出来了,想要求出有多少个连续帧,有两种情况:
-
(首帧第二个字节代表的有效字节数据长度 - 6)% 7 = 0 的情况下
连续帧个数 = (首帧第二个字节代表的有效字节数据长度 - 6)/ 7
-
(首帧第二个字节代表的有效字节数据长度 - 6)% 7 > 0 的情况下
连续帧个数 = (首帧第二个字节代表的有效字节数据长度 - 6)/ 7 + 1
注意:之所以要除以7,是因为,连续帧的第一个字节,不是有效字节数据
可以验证一下,当首帧第二个字节为 0x23 也就是十进制的 35 时,有效字节长度为 35 个,通过上述的公式计算出 连续帧个数 = (35 -6)/ 7 = 4.1
,所以需要 5 个连续帧。
通过下面的图片我们数一下,进行验证发现,确实需要5个连续帧:
c#托管和非托管混合编程
...使用C++/CLI介绍项目存档一直是企业的采用的做法,而是事实证明他们也是对的!对于一个程序员,这是几千men-days的工作量。为什么不开发一小段代码去重新利用那段代码,项目。现在提供了一个渐渐的 查看详情
代码实测:给redis中的key取一个正确的名字多么重要(代码片段)
redis对写入的key长度有限制吗?太长的key对性能有影响吗?key越长对性能影响越大?如何评估键长度对性能的影响?talkischeap,showmethecode!今天我们一起用代码来验证一下key的长度对redis读取key的性能影响。网络环境:本地内存:8Gr... 查看详情
人工智能人才争抢白热化?学好数学才能c位出道
...论与算法息息相关。线性代数:如何将研究对象形式化?事实上,线性代数不仅仅是人工智能的基础,更是现代数学和以现代数学作为主要分析方法的众多学科的基础。从量子力学到图像处理都离不开向量和矩阵的使用。而在向... 查看详情
游戏编程学习目录
...菜鸡。在保持大脑想法活跃的同时,最重要的还是将技术学好。毕竟九层之台,起于垒土。 对于游戏编程,最重要的是要先将C#和Unity学会。我总结了这两块的知识点: C#:&n 查看详情
c#异步编程----thread(代码片段)
一、问题由来多线程能实现的基础: 1、CPU运行速度太快,硬件处理速度跟不上,所以操作系统进行分时间片管理。这样,宏观角度来说是多线程并发 ,看起来是同一时刻执行了不同的操作。但是从微观角度来讲,同一... 查看详情
第1次作业(代码片段)
...言是一种结构化语言,是大部分编程语言的基础,c语言学好了,以后的java,c#以及更多的编程语言才有可能学好。下面就跟南宁达内小编一起,要学好c语言必须了解的四点:1、课前认真预习,把下一节要上的内容先自己看一遍... 查看详情
代数的历史:学好数学的两对辩证矛盾
一是数学的抽象与具体直观,二是数学的内在逻辑与形成逻辑。一夜之间读完了人民邮电出版社的新书《代数的历史》,脑海中满满地就是两对矛盾——并不是“逻辑矛盾”,而是辩证唯物主义所讲的“辩证矛盾”... 查看详情
算法大神对小码农说环形链表可以单独拿出来讲讲(代码片段)
...么一种情况呢。就是在环中一直交错永远遇不上?请证明一下。==证明:==这里就又衍生出了一个问题就是slow与fast只要是步差为一就可以相遇====2.为什么slow走一 查看详情
python入门-2编程基本概念:13字符串-unicode字符集-三种创建字符串的方式-len()(代码片段)
...人初学编程时,总是担心自己数学不行,潜意识里认为数学好才能编程。实际上,大多数程序员打交道最多的是“字符串”而不是“数字”。因为,编程是用来解决现实问题的,因此逻辑思维的重要性远远超过数学... 查看详情
高级码农设计的程序能解耦,是多么重要的一件事情!(代码片段)
...他人都能有所收获!😄一、前言能解耦,是多么重要的一件事情!摔杯为号、看我眼色行事、见南面火起,这是在嘎哈么?这其实是在通过事物传播进行解耦引线和炸弹,仅仅是这样的一个解耦 查看详情
注解开发(代码片段)
使用注解开发面向接口编程-大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程-根本原因:解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得... 查看详情
还在用clickhouse?事实证明es更强大!(代码片段)
点击关注公众号,实用技术文章及时了解来源:zhuanlan.zhihu.com/p/353296392Elasticsearch是一个实时的分布式搜索分析引擎,它的底层是构建在Lucene之上的。简单来说是通过扩展Lucene的搜索能力,使其具有分布式的功能。... 查看详情
数论杂谈——欧几里得算法及扩展欧几里得(代码片段)
...什么区别。欧几里得法辗转相除法求最大公约数我们可以证明gcd(a,b)=gcd(b,a%b),也就是我国古代数学智慧的结晶,更相损减术。并且一直递归下去,直到b的值为零,最大公约数值即为a。在这里就不给出详细证明了,大家可以代几... 查看详情
[数学推导]aw3782.点(推公式+数学推导+数学证明+cf76e)(代码片段)
文章目录1.题目来源2.题目解析1.题目来源链接:3782.点2.题目解析两点之间距离,为了不重复计算,给每个点编号,并定义其有序性。然后发现,x和y完全可以独立计算。然后推公式即可,公式中有重要的优... 查看详情
elasticsearch:实践指南(代码片段)
...较小的集群有更多的问题。这与较小的集群更易于管理的事实一致。然而,人们通常会认为集群越大,它对公司就越重要,因此会有更多的资源用于维护它并防止问题发生。更重要的是,El 查看详情
编程基础的重要性(程序员之路)
...数据结构,操作系统,计算机体系结构,编译原理等课程学好,对计算机的体系,CPU本身,操作系统内核,系统平台,面向对象编程,程序的性能等要有深层 查看详情
《天天数学》连载53:二月二十二日(代码片段)
2月22日XXII数学格言我不相信政治算术。——亚当·斯密数学习题补角对余角:∠A的补角3倍于∠A的余角,那么∠A多少度?古今评注从数学角度来讲,混沌并非意味着完全的混乱或彻底的不可预见性,而是一种有序的无序性。我... 查看详情
不用blazorwebassembly,开发在浏览器端编译和运行c#代码的网站(代码片段)
...sembly以及Roslyn技术。一、为什么要开发这样的工具?对于编程初学者来讲,开发环境的安装配置是一个令人头疼的事情,如果能让初学者不用做任何的安装配置,直接打开浏览器就能编写、运行代码,那么这将会大大降低编程初... 查看详情