码迷,mamicode.com
首页 > 其他好文 > 详细

自己写的一个帧处理代码,请多多指教

时间:2014-07-26 01:17:37      阅读:305      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   数据   for   

这段时间在一个项目中负责程序与下位机USB设备的通讯。将接收到的USB数据做帧处理之后做成一个完整的帧送入队列中等待上层应用对帧数据进行解析。

相信很多人在做与下位机通讯的项目的时候,都会为帧处理烦恼。因为上位机在接收数据的时候,由于收到操作系统调度的影响,有时候收到的是半帧,有时候收到的是一帧半数据。如果不做帧处理的话,就会严重丢包。

在项目中我写了一个帧处理代码,经过测试验证很稳定。拿出来分享一下,也请大家多多指教。

我们项目中的协议是<<.................>>这样的。第5、6字节是帧长度。帧处理采用状态机的概念。

代码如下:

1、状态枚举

 1         public enum FrameCheckState
 2        { 
 3             HandleStart,
 4             OneMark,
 5             TwoMark,
 6             CmdOne,
 7             CmdTwo,
 8             LenghtOne,
 9             LenghtTwo
10         }    

2、使用到的全部变量

bubuko.com,布布扣
 1 //USB读取缓存区
 2         static byte[] readBuffer;
 3         //帧缓存区
 4         static byte[] frameBuffer;
 5         //帧缓存区中等待处理标记
 6         static int _getIndex;
 7         static int GetIndex
 8         {
 9             get { return _getIndex; }
10             set
11             {
12                 if (value > 0)
13                     _getIndex = (value >= frameBuffer.Length) ? (value - frameBuffer.Length) : value;
14                 else
15                     _getIndex = 0;
16             }
17         }
18         //帧缓存区中已经接收到的标记
19         static int _nowIndex;
20         static int NowIndex
21         {
22             get { return _nowIndex; }
23             set
24             {
25                 if (value > 0)
26                     _nowIndex = (value >= frameBuffer.Length) ? (value - frameBuffer.Length) : value;
27                 else
28                     _nowIndex = 0;
29             }
30         }
31         static int indexTmp;       
32         //帧处理当前状态
33         static myEnums.FrameCheckState FrameState = myEnums.FrameCheckState.HandleStart;
34         //帧处理需要用的全局变量
35         static int getLength = 0, getCmd = 0;
36         static byte[] bgetLength = new byte[2], bgetCmd = new byte[2];
View Code

3、线程循环读USB

bubuko.com,布布扣
 1 /// <summary>
 2         /// 线程循环读取USB缓冲区
 3         /// </summary>
 4         static void ReadCmd()
 5         {
 6             byte[]buffer=new byte[usbReader.ReadBufferSize];
 7             int transferlength=0;
 8             try
 9             {
10                 while(true)
11                 {
12                     usbReader.Read(buffer, Consts.ReadTimeOut, out transferlength);
13 
14                     if(transferlength!=0)
15                     {
16                         for(int i=0;i<transferlength;i++)
17                         {
18                             frameBuffer[GetIndex] = buffer[i];
19                             GetIndex++;
20 
21                             //Console.Write(buffer[i].ToString("X2") + " ");
22                         }
23                         //Console.WriteLine();
24 
25                         GetFrameHandle();
26                     }
27                     Thread.Sleep(Consts.ReadSleepTime);
28                 }
29             }
30             catch
31             {
32                 Console.WriteLine("读取USB错误");
33             }
34         }
View Code

4、帧处理

bubuko.com,布布扣
  1 /// <summary>
  2         /// 帧处理方法
  3         /// </summary>
  4         private static void GetFrameHandle()
  5         {
  6             while (true)
  7             {
  8                 if (NowIndex == GetIndex)
  9                     return;
 10 
 11                 switch (FrameState)
 12                 {
 13                     case myEnums.FrameCheckState.HandleStart:
 14                         if (frameBuffer[NowIndex] == <)
 15                             FrameState = myEnums.FrameCheckState.OneMark;
 16 
 17                         NowIndex++;
 18                         break;
 19 
 20                     case myEnums.FrameCheckState.OneMark:
 21                         if (frameBuffer[NowIndex] == <)
 22                         {
 23                             indexTmp = NowIndex;
 24                             FrameState = myEnums.FrameCheckState.TwoMark;
 25                         }
 26                         else
 27                             FrameState = myEnums.FrameCheckState.HandleStart;
 28 
 29                         NowIndex++;
 30                         break;
 31 
 32                     case myEnums.FrameCheckState.TwoMark:
 33                         FrameState = myEnums.FrameCheckState.CmdOne;
 34                         bgetCmd[0] = frameBuffer[NowIndex];
 35                         NowIndex++;
 36                         break;
 37 
 38                     case myEnums.FrameCheckState.CmdOne:
 39                         FrameState = myEnums.FrameCheckState.CmdTwo;
 40                         bgetCmd[1] = frameBuffer[NowIndex];
 41                         getCmd = BitConverter.ToInt16(bgetCmd, 0);
 42                         NowIndex++;
 43                         break;
 44 
 45                     case myEnums.FrameCheckState.CmdTwo:
 46                         FrameState = myEnums.FrameCheckState.LenghtOne;
 47                         bgetLength[0] = frameBuffer[NowIndex];
 48                         NowIndex++;
 49                         break;
 50 
 51                     case myEnums.FrameCheckState.LenghtOne:
 52                         FrameState = myEnums.FrameCheckState.LenghtTwo;
 53                         bgetLength[1] = frameBuffer[NowIndex];
 54                         getLength = BitConverter.ToInt16(bgetLength, 0);
 55                         NowIndex++;
 56                         break;
 57 
 58                     case myEnums.FrameCheckState.LenghtTwo:
 59                         //获取到的帧长度超过缓冲池的长度,或者比12小,说明接收到的数据是错误的
 60                         //12是因为能接收到的信息,最短的长度为12.
 61                         if (getLength > frameBuffer.Length || getLength < 12)
 62                         {
 63                             FrameState = myEnums.FrameCheckState.HandleStart;
 64                             return;
 65                         }
 66 
 67                         //6是因为 ‘<<‘+cmd+length=6,NowIndex此时指在length的下一位。
 68                         if (NowIndex > GetIndex)
 69                         {
 70                             if (getLength > (GetIndex + frameBuffer.Length - NowIndex + 6))
 71                                 return;
 72                         }
 73                         else
 74                         {
 75                             if (getLength > GetIndex - NowIndex + 6)
 76                                 return;
 77                         }
 78 
 79                         DataBeans.Frame myFrame = new DataBeans.Frame();
 80                         byte[] myData = new byte[getLength];
 81                         myFrame.cmd = getCmd;
 82                         myFrame.length = getLength;
 83                         myFrame.data = myData;
 84 
 85                         myFrame.data[0] = 0x3C;
 86                         myFrame.data[1] = 0x3C;
 87                         myFrame.data[2] = bgetCmd[0];
 88                         myFrame.data[3] = bgetCmd[1];
 89                         myFrame.data[4] = bgetLength[0];
 90                         myFrame.data[5] = bgetLength[1];
 91                         for (int i = 6; i < getLength; i++)
 92                         {
 93                             myFrame.data[i] = frameBuffer[NowIndex];
 94                             NowIndex++;
 95                         }
 96 
 97                         //Console.Write("\t\t");
 98                         //for (int i = 0; i < myFrame.data.Length;i++ )
 99                         //{
100                         //    Console.Write(myFrame.data[i].ToString("X2") + " ");
101                         //}
102                         //Console.WriteLine();
103 
104                         //帧的最后的确是结束标记‘>>‘,视为完整的一帧,送入队列
105                         if (myFrame.data[getLength - 1] == > && myFrame.data[getLength - 2] == >)
106                             DataBeans.DataLists.setFrame(myFrame);
107                         //否则的话,不是一个正确的帧,回退到起始标记的下一位处重新做帧扫描
108                         else
109                             NowIndex = indexTmp;                     
110 
111                         FrameState = myEnums.FrameCheckState.HandleStart;
112                         break;
113 
114                     default:
115                         FrameState = myEnums.FrameCheckState.HandleStart;
116                         break;
117                 }
118             }
119         }
View Code

呵呵,0x3C=‘<‘  0x3E=‘>‘

自己写的一个帧处理代码,请多多指教,布布扣,bubuko.com

自己写的一个帧处理代码,请多多指教

标签:style   blog   http   color   使用   os   数据   for   

原文地址:http://www.cnblogs.com/scm-forever/p/3868882.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!