C# 串口操做系列(5)--通信库雏形

C# 串口操做系列(5)--通信库雏形

标签: 通信c#数据分析byteclassstring
 分类:
 

串口是很简单的,编写基于串口的程序也很容易。新手们除了要面对一堆的生僻概念,以及跨线程访问的细节,还有一个须要跨越的难题,就是协议解析,上一篇已经说明了:数组

一个二进制格式的协议通常包含: 协议头 + 数据段长度 + 数据  + 校验缓存

一个Ascii格式的文本协议,通常包含: 数据头 + 正文 + 数据结束标识框架

相似的命令可能不少,相似的代码也会重复写不少次。对于我,并不以为这个有任何难度,可是,不少时候,须要写点相似东西的时候呢,我每每不想写,不是别的,要搭建一个这样的框架,这绝对是个体力活,并且还须要耐心细心ide

从我上一次带项目,我就开始考虑编写通用的一个通信库,支持不少功能,不过和公司内容结合紧密,不适合开源,更不适合推广。我从新组织、抽象了各个概念。但愿能让新人朋友减小学习难度,更快的投入到其余方面。post

 

请注意,此文章我也不知道如何概括,不算科普,不能算类库的介绍,我是在介绍如何设计一个这样的通信库。学习

通信库,并不是串口库,因此,我但愿有一个基类,能够描述各类通信方法的基类或接口,微软已经这么作了,他把这个叫作Stream。我认为很差的理由是,提供了Length属性、peek方法、seek方法却没法使用,不少方法和属性是不支持的,若是使用这个类操做硬件,就像一颗地雷,不当心就会写一个不支持的操做,并且会在运行时报错。因此,我但愿能针对流设备的硬件,从新设计,我抽象出了一个接口:ICommunication。提供基本的打开、关闭、读写、字符集和有效数据长度等流设备的特性和操做。this

为了能有一个通用的配置类,我定义了一个接口:ICommunicationSetting。spa

当你实现一个设备的时候,你须要实现ICommunication,还须要编写一个设置的类,去实现ICommunicationSetting接口。别以为麻烦,这是为了能抽象的好,编写一个一劳永逸不用常常重写的通用代码。有了2个接口,我甚至能够开始编写依赖此接口的功能或软件了。固然,我还有须要写有关协议的分析。.net

既然协议是分2种,那天然要编写BinaryXXX和TextXXX,没错,有这样2个类。

考虑的更详细一点,任何数据,都不是无限期有效的,好比你获取下位机发来的电压,过了几秒了,应该就无效了,因此要考虑定时失效,因而我实现了有效性检查。数据要在字节数组中查找,分析,通知。因此这些公共的部分,我抽出来了,我写了一个接口,叫作:IAnalyzer,并编写了默认的实现,因而有了AnalyzeResult类,同时,区分2种协议方式,建立了子类:BinaryAnalyzeResult和TextAnalyzeResult。

那么,谁来使用ICommunication,IAnalyzer呢?放心,联系有点紧密,我不会撒手扔给外面的,这样作反而更复杂了,不是么。因此我写了一个带有分析功能的类:WyzComm。

使用通信库的

这个类实现了数据的采集、缓存、分析器的调用,以及事件调用的通知。数据死锁的控制,全部你认为的麻烦事情,都在这里作了。那么,我编写这个类的时候,我确定不知道将来有多少种协议是否是?那怎么办呢?我没法写死分析器,因此,我编写了接口:IAnalyzerCollection,由于文章从串口提及,我首先提供了串口的实现:

SerialPort(此类和微软的那个名字同样而已,但不是同一个),实现了ICommunication接口,我定义了一个SerialPortSetting类,实现了ICommunicationSetting。

至此。通信库的框架就完成了。而这也就是使用通信库所须要关注的全部内容。下面,为了能进行实际的演示,我编写了简单的实现。来演示一种功能,假设我有个程序,须要同时分析二进制数据格式和ASCII的文本数据格式,数据各不相同,使用了通信库以后,我不须要重写数据的缓存、关闭的死锁处理、数据对界面的通知。我只须要编写2个协议类,和1个协议集合类。个人数据分析工做就完成了。

 

首先是一个文本协议,协议头是WYZ,协议尾是回车换行,中间是一个整形数字。我只须要设置好头、尾,编写数据分析。

 

[c-sharp]  view plain  copy
 
  1. public class MyData1 : TextAnalyzeResult<int>  
  2. {  
  3.     public MyData1()  
  4.     {  
  5.         this.BeginOfLine = "WYZ";  
  6.         this.EndOfLine = "/r/n";  
  7.     }  
  8.   
  9.     public override void Analyze()  
  10.     {  
  11.         string s = Encoding.GetString(Raw);  
  12.         Match m = Regex.Match(s, "//d+");  
  13.         if (m.Success)  
  14.         {  
  15.             this.Data = int.Parse(m.Value);  
  16.             this.Valid = true;  
  17.         }  
  18.     }  
  19. }  

 

 

而后我定义了一个二进制协议,分析一条数据包含2个子项。

我首先定义这个数据的具体类型

 

[c-sharp]  view plain  copy
 
  1. public class SampleData  
  2. {  
  3.     public int Version { get; set; }  
  4.     public float Voltage { get; set; }  
  5.     public SampleData()  
  6.     {  
  7.         Version = 0;  
  8.         Voltage = 0;  
  9.     }  
  10.     public override string ToString()  
  11.     {  
  12.         return string.Format("{0},{1}", Version.ToString(), Voltage.ToString());  
  13.     }  
  14. }  

 

而后我编写协议分析类

 

[c-sharp]  view plain  copy
 
  1. public class MyData2 : BinaryAnalyzeResult<SampleData>  
  2. {  
  3.     public MyData2()  
  4.     {  
  5.         this._mask = new byte[] { 0xAA, 0xBB, 0xCC };  
  6.         this.TimeOut = 5;//超过5秒,收不到数据,则此数据无效。  
  7.         //自定义校验方法,演示为逐个相加和随便一个数字取模,我选择的是42  
  8.         this.checksum = (buf, offset, count) =>  
  9.             {  
  10.                 byte checksum = 0;  
  11.                 for (int i = offset; i < offset + count; i++)  
  12.                 {  
  13.                     checksum = (byte)((checksum + buf[i]) % 42);  
  14.                 }  
  15.                 return checksum;  
  16.             };  
  17.     }  
  18.   
  19.     public override void Analyze()  
  20.     {  
  21.         int offset = _mask.Length + LenLength;//_mask.Length表示标记后的一个字节,_mask.Length+1表示标记后的第二个字节,有一个字节表示长度。  
  22.         this.Data.Version = BitConverter.ToInt32(Raw, offset + 0);  
  23.         this.Data.Voltage = BitConverter.ToSingle(Raw, offset + 4);  
  24.         this.Valid = true;//注意要设置数据有效状态  
  25.     }  
  26. }  

 

 

完成了。一个基于串口的,同时分析2种数据的,数据具备有效性判断,支持独立数据通知界面,总体原始数据缓存显示的功能。完成了。

为了演示功能,我写了新的校验方式,固然,你不用管,默认已经支持了异或校验,后续还会把经常使用校验都添加进去,crc16,crc32,奇偶校验等。

 

模拟发送数据为:

文本格式发送:WYZ123<CR><LF>

二进制格式发送:AA BB CC 08 0A 00 00 00 FA 3E F7 42 05

 

vs2008工程项目源码范例

 
4
相关文章
相关标签/搜索