草庐IT

C# 事实证明学好数学对编程来讲是多么重要

cgsthtm 2023-04-21 原文

文章目录

背景

做上位机开发时,上位机和下位机如何进行通讯,一般取决于下位机。有这样一个通信协议:

  • 当上位机给下位机发送 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# 事实证明学好数学对编程来讲是多么重要的更多相关文章

  1. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  5. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  6. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  7. ruby - 如何以编程方式删除实例上的 "singleton information"以使其编码(marshal)? - 2

    我创建了一个由于“在运行时执行的单例元类定义”而无法编码的对象(这段代码的描述是否正确?)。这是通过以下代码执行的:#defineclassXthatmyusesingletonclassmetaprogrammingfeatures#throughcallofmethod:break_marshalling!classXdefbreak_marshalling!meta_class=class我该怎么做才能使对象编码正确?是否可以从对象instance_of_x的classX中“移除”单例组件?我真的需要一个建议,因为我们的一些对象需要通过Marshal.dump序列化机制进行缓存。

  8. Ruby 元编程问题 - 2

    我正在查看Ruby日志记录库Logging.logger方法并从sourceatgithub提出问题与这段代码有关:logger=::Logging::Logger.new(name)logger.add_appendersappenderlogger.additive=falseclass我知道类 最佳答案 这实际上删除了方法(当它实际被执行时)。这是确保close不会被调用两次的保障措施。看起来好像有嵌套的“class 关于Ruby元编程问题,我们在StackOverflow上找到一

  9. ruby - Paperclip:以编程方式分配图像并设置其名称 - 2

    使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案

  10. ruby - 如何以编程方式检查证书是否已被吊销? - 2

    我正在开发一个xcode自动构建系统。在执行一些预构建验证时,我想检查指定的证书文件是否已被撤销。我了解securityverify-cert验证其他证书属性但不验证吊销。我如何检查撤销?我正在用Ruby编写构建系统,但我对任何语言的想法都持开放态度。我阅读了这个答案(Openssl-Howtocheckifacertificateisrevokedornot),但指向底部的链接(DoesOpenSSLautomaticallyhandleCRLs(CertificateRevocationLists)now?)进入的Material对我的目的来说有点过于复杂(用户上传已撤销的证书是一

随机推荐