⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linklaypacket.cs

📁 该项目实现在.net 2003上
💻 CS
字号:
using System;
using System.Collections;
using System.Threading;
using System.Diagnostics;

namespace ctd.E1Analyzer.LinkLayHandlerPacket
{
	/// <summary>
	/// 
	/// </summary>
	/// 
	public class DataEntry
	{
		public DataEntry(int i)
		{
			length = i;
			szData = new byte[i];
		}
		private int length;
		public byte []szData;
		public int Length
		{
			set
			{
				length = value;
			}
			get
			{
				return length;
			}
		}
		public static DataEntry operator + (DataEntry leftEntry,DataEntry rightEntry)
		{
			DataEntry dtEntry = new DataEntry(leftEntry.Length + rightEntry.Length);
			
			Array.Copy(leftEntry.szData,0,dtEntry.szData,0,leftEntry.Length);
			Array.Copy(rightEntry.szData,0,dtEntry.szData,leftEntry.Length,rightEntry.Length);
			
			return dtEntry;

  
		}
	}
	/// <summary>
	/// 该类维护一个串口字节数据缓冲队列---m_RecBytesList,---完成从字节数据缓冲队列中取出一原始帧,并解析帧,完成Crc校验
	/// 给类维护一个发送帧队列m_SndDataList,---完成成帧、CRC校验、和字符检测
	/// 完成向发送帧队列m_SndDataList尾部添加数据帧
	/// </summary>
	public class LinkLayerDataHandler
	{
        private const int MAX_FRAME_LENGTH = 64;          //数据帧最大字节个数
		private const byte FRAME_HEAD = 0x7e;
		private const byte FRAME_TAIL = 0x7f;

		public const int MAX_SND_LIST_SIZE = 200;        //发送缓冲区最大尺寸
		public ArrayList m_RecBytesList = new ArrayList();//接收字节缓冲区
        public ArrayList m_SndDataList = new ArrayList();//发送帧缓冲区,从界面得来(其中的DataEntry 不包括帧头、帧尾、校验码)
		
		/// <summary>
		/// 向接收字节缓冲区末尾添加字节数组 
		/// </summary>
		/// <param name="data"></param>
		public void AddBytesToTail(byte[] data)
		{
            //
			m_RecBytesList.AddRange(data); //可以麽,这样,如果不行用下边的
		
		}
		/// <summary>
		/// 该函数完成从接收字节缓冲区获得一应用帧(完成字符检测和crc校验)
		/// </summary>
		/// <returns>
		/// 返回不包括头、尾、校验三个字节的一个净荷消息帧
		/// </returns>
		public byte[] GetOneFrameFromRecBytesList()
		{                                          
			//
			int headIndex = 0;
			int tailIndex = 0;
			byte[] outBytes = null;
			ArrayList outByteList = new ArrayList();
            byte [] oneOriginFrame;//不包括帧头、帧尾、校验字
			
			byte FCS = 0;
			byte oldFCS = 0;
			try
			{
				if(m_RecBytesList.Count < 5)//因为最短帧为5个字节
					return outBytes;

				headIndex = m_RecBytesList.IndexOf(FRAME_HEAD);
				tailIndex = m_RecBytesList.IndexOf(FRAME_TAIL);
				if(headIndex < 0 || tailIndex < 0)
				{
					return outBytes;
				}

				if(headIndex >= tailIndex)//去掉废弃部分
				{
					m_RecBytesList.RemoveRange(0,headIndex);
					return outBytes;
				}
				//以下两行要特别注意
				if(tailIndex < m_RecBytesList.Count - 1)
				{
					if((byte)m_RecBytesList[tailIndex + 1] == FRAME_TAIL)
						tailIndex += 1;
				}
				//
				if(tailIndex > headIndex)//查找到一帧
				{
					
					oneOriginFrame = new byte[tailIndex - headIndex + 1 - 2 ];
					//copy one original frame to oneOriginFrame
					m_RecBytesList.CopyTo(headIndex + 1,oneOriginFrame,0,tailIndex - headIndex + 1 - 2);
					//delete data from m_Queue
					m_RecBytesList.RemoveRange(0,tailIndex + 1);
					//检查帧序列
					try
					{
						for(int i = 0; i < oneOriginFrame.Length;i++)
						{
							if(oneOriginFrame[i] == 0x7D)
							{
								i += 1;
								outByteList.Add((byte)(oneOriginFrame[i]^0x20));
							}
							else
							{
								outByteList.Add((byte)oneOriginFrame[i]);
							}
						}
					}
					catch(Exception e)
					{
						Debug.WriteLine("public byte[] GetOneFrameFromRecBytesList():{0}",e.Message);
					}

					int num = outByteList.Count;//
                    //
					//原始校验字 
					oldFCS = (byte)outByteList[num - 1];
					//
					byte []data = new byte[num - 1];//
					outByteList.CopyTo(0,data,0,num-1);
					//重新计算crc校验字
					FCS = CRC.Calculate(data);
					//
					if(FCS == oldFCS)//校验通过
					{
						try
						{
							int count = outByteList.Count;
							outBytes = new byte[count];
							outByteList.CopyTo(0,outBytes,0,count);
						}
						catch(Exception e)
						{
							Debug.WriteLine("if(FCS == oldFCS)//校验通过{0}",e.Message);
						}
										
					}
					else
					{
						outBytes = null;
						Debug.WriteLine("!!!!!!!!!CRC校验错误");
					}
				}
				else
				{
					if(m_RecBytesList.Count > 1000)//防止缓冲区字符过多
					{
						m_RecBytesList.Clear();
						Debug.WriteLine("缓冲区字符过多,已经清理...");
					}
					//throw(new ApplicationException("缓冲区字符过多,已经清理..."));
					outBytes = null;
				}
			}
			catch(Exception e)
			{
				Debug.WriteLine("public byte[] GetOneFrameFromRecBytesList(){0}",e.Message);
				Debug.WriteLine(e.Message);
			}
			return outBytes;

            
		}
		/// <summary>
		/// 完成成帧和字符检测、以及CRC校验
		/// </summary>
		/// <returns>
		/// 返回一串行完整帧,提交串口发送
		/// </returns>
		public byte[] GetOneFrameFromSndDataList()
		{
			DataEntry dtEntry;

			byte [] originBytes;//原始数据帧字节
			byte [] originBytesIncFcs;//原始数据帧-包含crc
			int originBytesNum; //原始数据帧长度
			
			byte [] outBytes = null;
			int outBytesNum;
			ArrayList outByteList = new ArrayList();
			lock(m_SndDataList)
			{
				if(m_SndDataList.Count != 0)
				{
				
					dtEntry = (DataEntry)m_SndDataList[0];
					m_SndDataList.RemoveAt(0);
				}
				else
					return outBytes;
			}
			if(dtEntry.Length != 0)
			{
				originBytesNum = dtEntry.Length;
				//crc checks
				byte FCS = CRC.Calculate(dtEntry.szData);
				//
				originBytes = new byte[originBytesNum + 1];
				Array.Copy(dtEntry.szData,0,originBytes,0,originBytesNum);
								
				originBytes[originBytesNum] = FCS;
				//生成可以发送的字符序列
				originBytesNum += 1;//因为添加了fcs,所以参加字符序列检测的字节数加1
				outByteList.Add((byte)FRAME_HEAD);

				for(int i = 0; i< originBytesNum; i++)
				{
					if(originBytes[i]==FRAME_HEAD 
						|| originBytes[i] == FRAME_TAIL
						|| originBytes[i] == 0x7D )
					{
						outByteList.Add((byte)0x7D);
						outByteList.Add((byte)(originBytes[i]^0x20));
					}
					else
					{
						outByteList.Add((byte)originBytes[i]);
					}
				}
				outByteList.Add((byte)FRAME_TAIL);

				outBytesNum = outByteList.Count;
				outBytes = new byte[outBytesNum];
				outByteList.CopyTo(0,outBytes,0,outBytesNum);
								
			}
			
			return outBytes;
			//
		}
		/// <summary>
		///在队列末尾添加一帧数据到 m_SndDataList
		/// </summary>
		/// <param name="data"></param>
		public void AddOneFrameToSndDataList(DataEntry dataEntry)
		{
			lock(m_SndDataList)
			{
				if(m_SndDataList.Count <= MAX_SND_LIST_SIZE)
				{
				   m_SndDataList.Add(dataEntry);
				}
				
			}
		}
		
	}
	public class CRC
	{
		public static byte Calculate(byte [] data)
		{
			byte FCS = 0;
			byte HIGH_BIT = 0;
			int num = data.Length;
			
			for(int i = 0; i < num; i++)
			{
				HIGH_BIT = (byte)(FCS & 0x80);
				FCS <<= 1;
				if(HIGH_BIT != 0)
					FCS |= 0x1;
				FCS ^= data[i];
			}
			return FCS;
		}
	}
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -