using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; using System.Threading; using System.Diagnostics; using System.Net.Sockets; using System.IO; namespace SerialDebug { class CSerialDebug { private Queue receiveQueue = new Queue(); private List sendList = new List(); private SerialPort _serialPort = new SerialPort(); private bool IsReceiveStart = false; private Thread receiveThread; private Thread parseThread; private bool IsSendStart = false; private Thread sendThread; private TimeSpan delayTime = new TimeSpan(10 * 100); // 100us private int LoopCount = 0; private int _ReceiveTimeOut = 3; private bool _SendThreadBusy = false; public delegate void ReceivedEventHandler(object sender, SerialDebugReceiveData e); public event ReceivedEventHandler ReceivedEvent; public delegate void SendCompletedEventHandler(object sender, SendCompletedEventArgs e); public event SendCompletedEventHandler SendCompletedEvent; public event EventHandler SendOverEvent; private AutoResetEvent waitReceiveEvent = new AutoResetEvent(false); private ManualResetEvent waitParseEvent = new ManualResetEvent(false); private ManualResetEvent uartReceivedEvent = new ManualResetEvent(false); public CSerialDebug(SerialPort sport) { _serialPort = sport; } public SerialPort serialPort { get { return _serialPort; } set { _serialPort = value; } } public int ReceiveTimeOut { get { return _ReceiveTimeOut; } set { _ReceiveTimeOut = value; } } public bool SendThreadBusy { get { return _SendThreadBusy; } } public void Start() { try { IsReceiveStart = true; lock (receiveQueue) { receiveQueue.Clear(); } lock (sendList) { sendList.Clear(); } uartReceivedEvent.Reset(); waitReceiveEvent.Reset(); waitParseEvent.Reset(); if (serialPort.IsOpen) { serialPort.Close(); } serialPort.Open(); serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); releaseThread(receiveThread); releaseThread(sendThread); receiveThread = new Thread(new ThreadStart(ReceiveThreadHandler)); receiveThread.IsBackground = true; receiveThread.Name = "receiveThread"; receiveThread.Start(); parseThread = new Thread(new ThreadStart(ParseThreadHandler)); parseThread.IsBackground = true; parseThread.Name = "parseThread"; parseThread.Start(); Send(sendList, 1); } catch (System.Exception ex) { throw ex; } } public void Stop() { try { IsReceiveStart = false; IsSendStart = false; if (serialPort != null) { lock (serialPort) { serialPort.DataReceived -= new SerialDataReceivedEventHandler(serialPort_DataReceived); if (serialPort.IsOpen) { serialPort.Close(); } } } releaseThread(receiveThread); } catch (System.Exception ex) { throw ex; } } public void StopReceive() { IsReceiveStart = false; } public void StopSend() { IsSendStart = false; waitParseEvent.Set(); waitParseEvent.Reset(); while (SendThreadBusy) { Thread.Sleep(10); } //releaseThread(sendThread); } public void Send(List list) { LoopCount = 1; Send(list, LoopCount); } public void Send(List list, int loop) { if (sendThread != null) { if (sendThread.IsAlive) { releaseThread(sendThread); } } LoopCount = loop; lock (sendList) { sendList.Clear(); } sendList = list; IsSendStart = true; sendThread = new Thread(new ThreadStart(SendThreadHandler)); sendThread.IsBackground = true; sendThread.Name = "sendThread"; sendThread.Start(); } private bool SerialPortWrite(byte[] bytes, int offset, int count) { if (_serialPort != null && _serialPort.IsOpen) { lock (_serialPort) { _serialPort.Write(bytes, offset, count); return true; } } return false; } void releaseThread(Thread th) { try { if (th != null) { lock (th) { if (th.IsAlive) { th.Abort(); } } } } catch (System.Exception ex) { Debug.WriteLine(ex.ToString()); } } void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (uartReceivedEvent != null) { uartReceivedEvent.Set(); } } /// /// 接收线程 /// private void ReceiveThreadHandler() { //byte[] receiveBytes = new byte[4 * 1024]; while (IsReceiveStart) { try { if (_serialPort.IsOpen) { try { bool IsNeedContinueReceive = false; int dataLen; if (uartReceivedEvent.WaitOne() || IsNeedContinueReceive) { uartReceivedEvent.Reset(); //DateTime beginTime = DateTime.Now; int buffSize = 0; do { buffSize = serialPort.BytesToRead; if (buffSize >= 4 * 1024) { IsNeedContinueReceive = true; break; } Thread.Sleep(ReceiveTimeOut); } while (buffSize != serialPort.BytesToRead); if (buffSize > 0) { byte[] receiveBytes = new byte[buffSize]; dataLen = serialPort.Read(receiveBytes, 0, receiveBytes.Length); if (dataLen > 0) { byte[] bytes = new byte[dataLen]; Array.Copy(receiveBytes, bytes, dataLen); lock (receiveQueue) { receiveQueue.Enqueue(new SerialDebugReceiveData(bytes)); } waitReceiveEvent.Set(); } } } } catch (System.Exception ex) { if (ex is ThreadInterruptedException) throw; Debug.WriteLine(ex.ToString()); } } else { Thread.Sleep(10); } } catch (System.Exception ex) { if (ex is ThreadInterruptedException) break; Debug.WriteLine(ex.ToString()); } } } /// /// 接收消息处理线程 /// private void ParseThreadHandler() { while (IsReceiveStart) { try { SerialDebugReceiveData data = null; lock (receiveQueue) { if (receiveQueue.Count > 0) { data = receiveQueue.Dequeue(); } } if (data != null) { if (ReceivedEvent != null) { ReceivedEvent(this, data); } waitParseEvent.Set(); } else { waitReceiveEvent.WaitOne(10); } } catch (Exception ex) { Console.WriteLine("数据处理线程:" + ex.Message); } } } /// /// 发送线程 /// private void SendThreadHandler() { bool IsFirstSend = true; if (LoopCount == 0) { LoopCount = int.MaxValue; } try { while (LoopCount > 0 && IsSendStart) { LoopCount--; waitParseEvent.Reset(); int index = 0; while (index < sendList.Count && IsSendStart) { _SendThreadBusy = true; CSendParam sendParam = null; lock (sendList) { sendParam = sendList[index]; } index++; if (sendParam != null) { bool DelayEnable = true; if (sendParam.Mode == SendParamMode.SendAfterLastSend) { if (IsFirstSend) { DelayEnable = false; } } else if (sendParam.Mode == SendParamMode.SendAfterReceived) { waitParseEvent.WaitOne(); } IsFirstSend = false; if (DelayEnable && sendParam.DelayTime > 0) { DateTime startTime = DateTime.Now; TimeSpan ts = DateTime.Now - startTime; while (ts.TotalMilliseconds < sendParam.DelayTime) { Thread.Sleep(delayTime); ts = DateTime.Now - startTime; if (!IsSendStart) { break; } } ; } if (IsSendStart && SerialPortWrite(sendParam.DataBytes, 0, sendParam.DataBytes.Length)) { if (SendCompletedEvent != null) { SendCompletedEventHandler handler = SendCompletedEvent; handler(this, new SendCompletedEventArgs(sendParam)); } } else { IsSendStart = false; } waitParseEvent.Reset(); } _SendThreadBusy = false; } } } catch (System.Exception ex) { Debug.WriteLine(ex.ToString()); } finally { if (SendOverEvent != null) { SendOverEvent(this, null); } } } } public class SerialDebugReceiveData : EventArgs { private readonly DateTime _ReceiveTime; private readonly byte[] _ReceiveData; private readonly int _DataLen; public SerialDebugReceiveData(byte[] data) { _ReceiveData = data; _ReceiveTime = DateTime.Now; if (data != null) { _DataLen = data.Length; } else { _DataLen = 0; } } public byte[] ReceiveData { get { return _ReceiveData; } } public DateTime ReceiveTime { get { return _ReceiveTime; } } public int DataLen { get { return _DataLen; } } public string TimeString { get { return string.Format("[{0}.{1:D3}]", _ReceiveTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), _ReceiveTime.Millisecond); } } public string HexString { get { return string.Format("{0} ", BitConverter.ToString(_ReceiveData).Replace('-', ' ')); } } public string ASCIIString { get { return System.Text.ASCIIEncoding.Default.GetString(_ReceiveData); } } public string DecString { get { StringBuilder sb = new StringBuilder(); foreach (byte b in _ReceiveData) { sb.AppendFormat("{0} ", Convert.ToInt32(b)); } return sb.ToString(); } } } public class SendCompletedEventArgs : EventArgs { private readonly DateTime _SendTime; private CSendParam _SendParam; public SendCompletedEventArgs(CSendParam sendParam) { _SendTime = DateTime.Now; _SendParam = sendParam; //if (sendParam!=null) //{ // _SendParam = new CSendParam(sendParam.Format, // sendParam.Mode, // sendParam.DelayTime, // sendParam.DataBytes, 0, sendParam.DataLen); //} //else //{ // _SendParam = null; //} } public DateTime SendTime { get { return _SendTime; } } public CSendParam SendParam { get { return _SendParam; } } public string TimeString { get { return string.Format("[{0}.{1:D3}]", _SendTime.ToString("yyyy-MM-dd HH:mm:ss"), _SendTime.Millisecond); } } } }