Files
2025-08-26 08:37:44 +08:00

563 lines
16 KiB
C#
Raw Permalink Blame History

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<SerialDebugReceiveData> receiveQueue = new Queue<SerialDebugReceiveData>();
private List<CSendParam> sendList = new List<CSendParam>();
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<CSendParam> list)
{
LoopCount = 1;
Send(list, LoopCount);
}
public void Send(List<CSendParam> 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();
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
/// </summary>
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());
}
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
/// </summary>
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("<22><><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD>̣߳<DFB3>" + ex.Message);
}
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
/// </summary>
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);
}
}
}
}