📄 linklaypacket.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 + -