using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.IO.Ports; using System.Windows.Forms; namespace Dispatch { internal class SerialPortEx { public SerialPortEx() { serialPort1 = new SerialPort(); serialPort1.PortName = "COM1"; serialPort1.BaudRate = 9600; serialPort1.StopBits = StopBits.One; serialPort1.Parity = Parity.None; serialPort1.DataBits = 8; serialPort1.ReceivedBytesThreshold = 1; serialPort1.ReadTimeout = 1000; serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived); thread = new Thread(ThreadHandler); } /************************************************************************/ /*添加了读写串口事件*/ /************************************************************************/ public event EventHandler ReadingData; public event EventHandler WritingData; void OnReadingData(EventArgs e) { if (ReadingData != null) { ReadingData(this, e); } } void OnWritingData(EventArgs e) { if (WritingData != null) { WritingData(this, e); } } public void Write(string text) { try { serialPort1.Write(text); OnWritingData(null); } catch (System.Exception ex) { throw new Exception("写串口:" + ex.Message); } } public void Write(byte[] buffer, int offset, int count) { try { serialPort1.Write(buffer, offset, count); OnWritingData(null); } catch (System.Exception ex) { throw new Exception("写串口:" + ex.Message); } } public void Write(char[] buffer, int offset, int count) { try { serialPort1.Write(buffer, offset, count); OnWritingData(null); } catch (System.Exception ex) { throw new Exception("写串口:" + ex.Message); } } public void Open() { try { if (!serialPort1.IsOpen) { serialPort1.Open(); if (thread != null) { if (thread.ThreadState == ThreadState.Suspended) thread.Resume(); else if (thread.ThreadState == ThreadState.Stopped || thread.ThreadState == ThreadState.Unstarted) { thread.Start(); } } else { thread = new Thread(ThreadHandler); thread.Start(); } } } catch (System.Exception ex) { throw new Exception("打开串口:" + ex.Message); } } public void Close() { try { serialPort1.Close(); if (thread != null && thread.ThreadState == ThreadState.Running) { if (done.WaitOne(500)) { thread.Suspend(); } thread.Suspend(); } receiveBuffer.Clear(); } catch (System.Exception ex) { throw new Exception("关闭串口:" + ex.Message); } } public SerialPort serialPort1; public List receiveBuffer = new List(2046); private object portLock = new object(); public delegate void MatchedParityHandler(object sender, PortDataEventArgs e); public event MatchedParityHandler MatchedParity; private Thread thread; private void OnMatchedParity(object sender, PortDataEventArgs e) { if (MatchedParity != null) { MatchedParity(sender, e); } } private class MyData { public object sender; public PortDataEventArgs e; } public void OnMatchParity(object o) { MyData data = o as MyData; Console.ForegroundColor = ConsoleColor.Yellow; //Console.WriteLine("所在线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString() + "类型:" + data.e.type + " " + Byte2HexString(data.e.data)); Console.ResetColor(); OnMatchedParity(data.sender, data.e); Thread.Sleep(500);//加延时是为了避免解析后有过长的操作占用系统资源 } public static string Byte2HexString(byte[] buffer) { StringBuilder builder = new StringBuilder(buffer.Length * 3); foreach (byte data in buffer) { builder.Append(Convert.ToString(data, 16).PadLeft(2, '0').PadRight(3, ' ')); } return builder.ToString().ToUpper(); } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { byte[] buffer = new byte[serialPort1.BytesToRead]; serialPort1.Read(buffer, 0, buffer.Length); OnReadingData(null); Console.ForegroundColor = ConsoleColor.Green; //Console.WriteLine("接收数据:" + Byte2HexString(buffer)); Console.ResetColor(); lock (portLock) { receiveBuffer.AddRange(buffer); } //Console.WriteLine("缓冲区数据:" + Byte2HexString(receiveBuffer.ToArray())); } public static byte XOR_Check(byte[] buffer, int count, int index = 0) { byte b = 0; for (int i = 0; i < count; i++) { b ^= buffer[index + i]; } return b; } int endCodeIndex = 8;//尾码索引号 int endCodeCount = 0;//找到尾码的次数 private byte[] DataHander(out int type) { type = -1; int i, j; if (receiveBuffer.Count >= 9) { i = receiveBuffer.FindIndex(0, b => b == 0x10); if (i != -1) { //Console.WriteLine("找到0x10,在位置:{0}", i); j = receiveBuffer.FindIndex(endCodeIndex, b => b == 0x03); if (j != -1 && j > i) { endCodeIndex = j; endCodeIndex++;//索引自加 endCodeCount++; //Console.WriteLine(string.Format("找到0x03,在位置:{0},endcodeIndex={1}", j, endCodeIndex)); if ((j - i + 1) == 10) { byte[] tempBuffer = new byte[10]; receiveBuffer.CopyTo(i, tempBuffer, 0, 10); if (XOR_Check(tempBuffer, 8) == tempBuffer[8]) { type = 2; lock (portLock) { receiveBuffer.RemoveRange(0, j + 1); endCodeIndex = 0;// endCodeCount = 0; } return tempBuffer; } else { //Console.WriteLine(string.Format("没通过校验:{0}", Byte2HexString(tempBuffer))); lock (portLock) { receiveBuffer.RemoveRange(0, j + 1); } } } else if (receiveBuffer.Count - i > 30)//如果数据长度超过30但校验没通过 { endCodeIndex = 0;// endCodeCount = 0; //Console.WriteLine(string.Format("0x10与0x03间数据过长:", Byte2HexString(receiveBuffer.ToArray()))); lock (portLock) { receiveBuffer.RemoveRange(0, j + 1); } } else if (j - i + 1 < 9) { //Console.WriteLine(string.Format("找到0x03,但0x03与0x10间数据过短,0x03位置:{0},0x10位置:{1}", j, i)); } else { //Console.WriteLine(string.Format("在找到0x03中没考虑的情况,0x03位置:{0},0x10位置:{1}", j, i)); } } else if (j != -1 && j < i) { endCodeIndex = 0;// endCodeCount = 0; //Console.WriteLine(string.Format("0x03位置:{0}小于0x10位置:{1},数据:{2}", j, i, Byte2HexString(receiveBuffer.ToArray()))); lock (portLock) { //receiveBuffer.RemoveAt(i); receiveBuffer.RemoveRange(0, j + 1); } } else if (/*j == -1 && */receiveBuffer.Count - i > 1000) { endCodeIndex = 0;// endCodeCount = 0; //Console.WriteLine(string.Format("数据量超过1000:", Byte2HexString(receiveBuffer.ToArray()))); lock (portLock) { //receiveBuffer.RemoveAt(i); receiveBuffer.RemoveRange(0, receiveBuffer.Count); } } else { //Console.WriteLine(string.Format("没考虑到情况,可能找到0x03,0x10位置:{0},0x03位置:{1},数据:{2}", Byte2HexString(receiveBuffer.ToArray()))); } } else { //Console.WriteLine(string.Format("0x10没找到:", Byte2HexString(receiveBuffer.ToArray()))); lock (portLock) { receiveBuffer.RemoveRange(0, receiveBuffer.Count); } } } return new byte[1] { 0 }; } AutoResetEvent done = new AutoResetEvent(true);//在处理数据的时候不允许被打断(只有在线程正常挂起时有效) public void ThreadHandler() { while (true) { if (serialPort1.IsOpen) { //Console.WriteLine("分析线程运行中..."); if (receiveBuffer.Count > 0) { done.Reset(); byte[] buffer; int type; buffer = DataHander(out type); PortDataEventArgs e = new PortDataEventArgs(); e.type = type; e.data = buffer; if (type != -1) { MyData data = new MyData(); data.sender = this; data.e = e; Thread t = new Thread(OnMatchParity); t.Start(data); //OnMatchedParity(this, e); Console.ForegroundColor = ConsoleColor.Blue; //Console.WriteLine("类型:" + type.ToString() + " " + Byte2HexString(buffer)); Console.ResetColor(); } } } Thread.Sleep(10); done.Set(); } } } internal class PortDataEventArgs : EventArgs { public byte[] data; public int type; } }