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

这段时间在一个项目中负责程序与下位机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、使用到的全部变量

 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];

3、线程循环读USB

 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         }

4、帧处理

  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         }

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

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

时间: 2024-11-04 12:22:23

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

java,请多多指教

记得当初学C语言的时候,第一个程序是"Hello World",而我java的第一个程序也是"Hello World".我想从事游戏开发设计方面的工作,我知道那会很难,而且会很久,但什么职业又不是这样来的呢?一本上千页的书,最初还不是从一张张白纸走过来的,谁知道它花了几年,十几年,甚至几十年才完成的.所以,学路漫漫,java,请多多指教! public class Hello { public static void main(String[] args) { Sy

把之前写的一个小东西代码分享出来

大家接触到流的输出输入和GUI就会自己写了,其实soeasy 所以不好意思拿出来,毕竟是小白,主要还是因为懒,FileDialog也懒得弄了,讲道理界面太丑,加了dialog也挺low,自己想留着用的可以自己去完善,基本上加些东西就ok了.如果你们复制过去发现没有图片,请不要紧张,因为图片在我这啊~~你们自己照着路径修改就好了,群里面有打包了的有图片的,有需要二次元 图片的可以私聊我哟..... 启动类:什么都木有,哈哈哈 1 package practice.AsceticJ; 2 3 /**

最近开始努力学python 写了一个python小代码:判断一个登陆程序,如果账号密码输错3次,锁定账号无法再登陆

1 count = 0 2 username = 'zhangsan' 3 userpassword = '111111' 4 5 f = open('lock.txt','r+') 6 file_list = f.readlines() 7 f.close() 8 #打开文件夹 读取数据 9 10 name = input("请输入用户名:") 11 12 if name in file_list: 13 print("您的账号被锁定!") 14 #判断文件夹中的

想了好久 请多多指教

条件:假设A公司光纤入网,isp给的是静态ip,应该是公网ip吧 然后搭建了DNS服务器和WEB服务器,(当然自己建了个企业网站,备过案) 目的是在使全世界的客户都能访问到A公司的企业网站 ---------------------------------------------------------------------------------------------------- 我在想这个能不能实现呢?或者说能实现,但是访问网站不稳定,还有哪些没有考虑到呢? 用到花生壳?dmz? 求解

总结上课知识点,(新手,请多多指教)

//基本内置类型//char ? ? ? ?//字符数据类型//short ? ? ? //短整型//int ? ? ? ? //整形//long ? ? ? ?//长整型//long long ? //更长的整形//float ? ? ? //单精度浮点数//double ? ? ?//双精度浮点数 //基本类型归类////1整形//char//unsigned char//signed char//short//unsigned short[int]//signed short[int]//

ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例

HTML代码 和js 代码 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="~/js/jquery-1.8.3.min.js"></

去年方百度首页播放器写的一个js代码,先记录一下,不支持火狐了,改天用autio改改

播放器内核使用的是 object 或embed 刚刚测试了下,最新的火狐不支持了,IE 360还能用,改天换成audio来做吧 这里先记录下来 支持下一曲,暂停,开始 使用方法很简单: 该代码很简单,使用js实现,使用方法很简单 1.引入css:<link href="css/StyleSheet.css" rel="stylesheet" type="text/css" />2.引入js:<script src="j

写的一个段落标签文字内容两端对齐的代码

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus®"> <meta name="Author" content=""> <meta name="

用jq代码写出一个轮播图。

由于项目的需要,需要写出一个图片预览的功能,在预览的同时如果预览的图片大于1,还要能够轮播,.所以,这就是一个从后台取图片的路径,然后轮播的一个功能.  当图片数为1时,不显示左右箭头以及轮播圆点. 下面是一个gif的demo: 首先,我们理清了实现的方式.我们先做出一个轮播图的效果. DEMO地址:https://codepen.io/Dios/pen/dzLMVJ 然后我们再通过一些js判断达到图中的效果.