革博士程序V1仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SSerialPort.cs 6.4 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. 
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.IO.Ports;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. namespace LeatherApp.Utils
  11. {
  12. public class SSerialPort
  13. {
  14. private SerialPort _serialPort;
  15. private readonly ConcurrentQueue<byte[]> _messageQueue;
  16. private readonly EventWaitHandle _messageWaitHandle;
  17. private int _receiveCount, _sendCount;
  18. private readonly object _lock;
  19. private int queueSize;
  20. public int ReceiveCount
  21. {
  22. get => _receiveCount;
  23. }
  24. public int SendCount
  25. {
  26. get => _sendCount;
  27. }
  28. /// <summary>
  29. ///
  30. /// </summary>
  31. /// <param name="com"></param>
  32. /// <param name="baud"></param>
  33. /// <param name="size">队列最大容量</param>
  34. public SSerialPort(string com, int baud,int size=-1)
  35. {
  36. // initialized
  37. _lock = new object();
  38. _receiveCount = 0;
  39. _sendCount = 0;
  40. _messageQueue = new ConcurrentQueue<byte[]>();
  41. _messageWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
  42. queueSize = size;
  43. // Open Com
  44. openCom(com.ToUpper(), baud);
  45. // Receive byte
  46. pushMessage();
  47. }
  48. private void openCom(string com, int baud)
  49. {
  50. // Open Com
  51. _serialPort = new SerialPort(com, baud);
  52. if (_serialPort.IsOpen) _serialPort.Close();
  53. // Set the read / write timeouts
  54. _serialPort.ReadTimeout = 500;
  55. _serialPort.WriteTimeout = 500;
  56. // Set read / write buffer Size,the default of value is 1MB
  57. _serialPort.ReadBufferSize = 1024 * 1024;
  58. _serialPort.WriteBufferSize = 1024 * 1024;
  59. _serialPort.Open();
  60. // Discard Buffer
  61. _serialPort.DiscardInBuffer();
  62. _serialPort.DiscardOutBuffer();
  63. }
  64. #region Static
  65. /// <summary>
  66. /// 获取当前计算机的串行端口名的数组
  67. /// </summary>
  68. /// <returns></returns>
  69. public static string[] getPortNames()
  70. {
  71. return SerialPort.GetPortNames();
  72. }
  73. /// <summary>
  74. /// 波特率
  75. /// </summary>
  76. /// <returns></returns>
  77. public static List<string> getBaudrateList()
  78. {
  79. return new List<string>()
  80. {
  81. "300",
  82. "600",
  83. "1200",
  84. "2400",
  85. "4800",
  86. "9600",
  87. "19200",
  88. "38400",
  89. "57600",
  90. "115200",
  91. "230400",
  92. "460800",
  93. "921600"
  94. };
  95. }
  96. #endregion
  97. #region Receive
  98. private void pushMessage()
  99. {
  100. _serialPort.DataReceived += (sender, e) =>
  101. {
  102. lock (_lock)
  103. {
  104. if (_serialPort.IsOpen == false) return;
  105. int length = _serialPort.BytesToRead;
  106. byte[] buffer = new byte[length];
  107. int readLen = _serialPort.Read(buffer, 0, length);
  108. API.OutputDebugString($"serialPort 缓存中长度:{length},实际读取长度:{readLen}.");
  109. if (readLen > 0)
  110. {
  111. _receiveCount += length;
  112. _messageQueue.Enqueue(buffer);
  113. byte[] outObj;
  114. while (queueSize > 0 && _messageQueue.Count > queueSize)
  115. {
  116. API.OutputDebugString($"serialPort 删除队列1项,队列中数量:{_messageQueue.Count},队列大小:{queueSize}");
  117. _messageQueue.TryDequeue(out outObj);
  118. }
  119. _messageWaitHandle.Set();
  120. }
  121. }
  122. };
  123. }
  124. /// <summary>
  125. /// 获取串口接受到的内容
  126. /// </summary>
  127. /// <param name="millisecondsToTimeout">取消息的超时时间</param>
  128. /// <returns>返回byte数组</returns>
  129. public byte[] getMessage(int millisecondsToTimeout = -1)
  130. {
  131. if (_messageQueue.TryDequeue(out var message))
  132. {
  133. return message;
  134. }
  135. if (_messageWaitHandle.WaitOne(millisecondsToTimeout))
  136. {
  137. if (_messageQueue.TryDequeue(out message))
  138. {
  139. return message;
  140. }
  141. }
  142. return default;
  143. }
  144. #endregion
  145. #region Send
  146. /// <summary>
  147. /// 发送消息(byte数组)
  148. /// </summary>
  149. /// <param name="buffer"></param>
  150. /// <param name="offset"></param>
  151. /// <param name="count"></param>
  152. public void send(byte[] buffer, int offset, int count)
  153. {
  154. lock (_lock)
  155. {
  156. _serialPort.Write(buffer, offset, count);
  157. //_sendCount += (count - offset);
  158. _sendCount += count;
  159. }
  160. }
  161. /// <summary>
  162. /// 发送消息(字符串)
  163. /// </summary>
  164. /// <param name="encoding">字符串编码方式,具体方式见<see cref="Encoding"/></param>
  165. /// <param name="message"></param>
  166. public void send(Encoding encoding, string message)
  167. {
  168. lock (_lock)
  169. {
  170. var buffer = encoding.GetBytes(message);
  171. _serialPort.Write(buffer, 0, buffer.Length);
  172. _sendCount += buffer.Length;
  173. }
  174. }
  175. #endregion
  176. /// <summary>
  177. /// 清空接受/发送总数统计
  178. /// </summary>
  179. public void clearCount()
  180. {
  181. lock (_lock)
  182. {
  183. _sendCount = 0;
  184. _receiveCount = 0;
  185. }
  186. }
  187. /// <summary>
  188. /// 关闭串口
  189. /// </summary>
  190. public void close()
  191. {
  192. _serialPort.Close();
  193. }
  194. }
  195. }