背景
做上位机开发时,上位机和下位机如何进行通讯,一般取决于下位机。有这样一个通信协议:
- 当上位机给下位机发送 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个连续帧:
|