本工作室开发的项目不少,积累的开发经验不少。现在和各位分享。今天分享的是串口处理数据程序,它的作用是是将从从USB或者硬件串口获取到的数据进行读取并将数据存储到相应的位置。每接受一个字节,触发一次DataReceived事件,读取串口所有数据;使用一个优先级低于读取串口数据的线程,该线程首先解析获得一个完整的帧。
以下是主要的代码:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{//串口数据来到
try
{
//this.InsertError("接收到串口数据" + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
string str = this.serialPort1.ReadExisting();
if (this.oThread == null || this.oThread.ThreadState == System.Threading.ThreadState.Stopped)
{
this.oThread = new Thread(new ThreadStart(this.DealSerialData));
//this.InsertError("重新new接受处理线程:" + DateTime.Now.ToShortDateString());
//this.textBox1.Text = this.textBox1.Text + System.Environment.NewLine + "重新new线程";
}
if (this.oThread.ThreadState == System.Threading.ThreadState.Unstarted)
{
this.oThread.Start();
//this.InsertError("串口接受数据处理线程重新开始");
}
this.TotalReadNum += str.Length;
Byte[] byteArray = new Byte[str.Length];
for (int i = 0; i < str.Length; i++)
byteArray[i] = Convert.ToByte(str[i]);
lock (this.ByteArray)
{
this.ByteArray.InsertRange(this.ByteArray.Count, byteArray);//将从串口读取的数据放到未处理字节数组byteArray中
//this.InsertError("将串口数据复制到缓存中" + MyCommandByteArrayToStr(byteArray)+"复制后缓存长度:"+ByteArray.Count);
}
}
catch (Exception ex)
{
this.InsertError("函数serialPort1_DataReceived出错" + ex.ToString());
}
}
private void DealSerialData()
{
//处理串口数据
try
{
Thread.Sleep(10);
//this.InsertError("进入串口接收数据处理线程");
int ByteArrayLength = 0;
lock (this.ByteArray)
{
ByteArrayLength = this.ByteArray.Count;
//this.InsertError("串口数据长度:" + ByteArrayLength);
}
while (ByteArrayLength >= 4)
{
//this.InsertError(ByteArrayLength);
string FrameControlByte = "0";//帧控制字
int FrameLength = -1;//帧总长度
ArrayList FrameByteArray = new ArrayList();//一个帧的字节数组
//this.InsertError("正在处理数据线程中");
bool HaveDeleteFrameHead = false;//是否已经删除帧头
while (ByteArrayLength >= 4)//至少要有4个字节才能开始解析
{
int deleteByteNum;//需要删除的字节数目
if (HaveDeleteFrameHead == false)
{//尚未删除帧头
lock (ByteArray)
{
if (Convert.ToByte(ByteArray[0]) == 0xaa && Convert.ToByte(ByteArray[1]) == 0x55)
{
deleteByteNum = 2;
this.ByteArray.RemoveRange(0, deleteByteNum);//删除帧头
ByteArrayLength = ByteArrayLength - 2;
HaveDeleteFrameHead = true;//读取本帧命令前,已经不需要再删除帧头,读取完一帧命令后,再将HaveDeleteFrameHead 设置为false
}
else
{
deleteByteNum = 1;
ByteArrayLength = ByteArrayLength - 1;
this.ByteArray.RemoveRange(0, deleteByteNum);//删除一个错误字节
this.InsertError("删除错误字节");
}
}
}
//帧头并不参与校验
lock (ByteArray)
{
FrameControlByte = this.MyByteToFixedLengthString(Convert.ToByte(this.ByteArray[0]));//第一个字节为帧控制字
FrameLength = 7 + Convert.ToInt32(this.ByteArray[1]);//ByteArray[1]为帧有效数据长度,加上控制、校验等7个字节
//this.InsertError("待处理的字节数" + this.ByteArray.Count.ToString() + " 帧长度" + FrameLength.ToString());
}
if (ByteArrayLength >= FrameLength)
{//如果当前帧已经完全读入,则复制当前帧的字节到CommByteArray中
// this.InsertError("待处理字节数大于帧长度,开始解析数据帧");
HaveDeleteFrameHead = false;
FrameByteArray.Clear();
for (int i = 0; i < FrameLength; i++)
FrameByteArray.Add(ByteArray[i]);
string strByteArray = "";
lock (this.ByteArray)
{
this.ByteArray.RemoveRange(0, FrameLength);
ByteArrayLength = ByteArray.Count;
}
this.WaitSerialTimeNum = 0;
this.DealReceiveCommandByteArray(FrameByteArray);//处理得到的字节帧
}
else
{
lock (this.ByteArray)
{
ByteArrayLength = ByteArray.Count;
}
}
}
}
}
catch (Exception ex)
{
this.InsertError("函数DealSerialData出错" + ex.ToString());
}
}
浙公网安备 33010602011771号