SerialPortEx.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.IO.Ports;
  7. using System.Windows.Forms;
  8. namespace Dispatch
  9. {
  10. internal class SerialPortEx
  11. {
  12. public SerialPortEx()
  13. {
  14. serialPort1 = new SerialPort();
  15. serialPort1.PortName = "COM1";
  16. serialPort1.BaudRate = 9600;
  17. serialPort1.StopBits = StopBits.One;
  18. serialPort1.Parity = Parity.None;
  19. serialPort1.DataBits = 8;
  20. serialPort1.ReceivedBytesThreshold = 1;
  21. serialPort1.ReadTimeout = 1000;
  22. serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
  23. thread = new Thread(ThreadHandler);
  24. }
  25. /************************************************************************/
  26. /*添加了读写串口事件*/
  27. /************************************************************************/
  28. public event EventHandler ReadingData;
  29. public event EventHandler WritingData;
  30. void OnReadingData(EventArgs e)
  31. {
  32. if (ReadingData != null)
  33. {
  34. ReadingData(this, e);
  35. }
  36. }
  37. void OnWritingData(EventArgs e)
  38. {
  39. if (WritingData != null)
  40. {
  41. WritingData(this, e);
  42. }
  43. }
  44. public void Write(string text)
  45. {
  46. try
  47. {
  48. serialPort1.Write(text);
  49. OnWritingData(null);
  50. }
  51. catch (System.Exception ex)
  52. {
  53. throw new Exception("写串口:" + ex.Message);
  54. }
  55. }
  56. public void Write(byte[] buffer, int offset, int count)
  57. {
  58. try
  59. {
  60. serialPort1.Write(buffer, offset, count);
  61. OnWritingData(null);
  62. }
  63. catch (System.Exception ex)
  64. {
  65. throw new Exception("写串口:" + ex.Message);
  66. }
  67. }
  68. public void Write(char[] buffer, int offset, int count)
  69. {
  70. try
  71. {
  72. serialPort1.Write(buffer, offset, count);
  73. OnWritingData(null);
  74. }
  75. catch (System.Exception ex)
  76. {
  77. throw new Exception("写串口:" + ex.Message);
  78. }
  79. }
  80. public void Open()
  81. {
  82. try
  83. {
  84. if (!serialPort1.IsOpen)
  85. {
  86. serialPort1.Open();
  87. if (thread != null)
  88. {
  89. if (thread.ThreadState == ThreadState.Suspended)
  90. thread.Resume();
  91. else if (thread.ThreadState == ThreadState.Stopped || thread.ThreadState == ThreadState.Unstarted)
  92. {
  93. thread.Start();
  94. }
  95. }
  96. else
  97. {
  98. thread = new Thread(ThreadHandler);
  99. thread.Start();
  100. }
  101. }
  102. }
  103. catch (System.Exception ex)
  104. {
  105. throw new Exception("打开串口:" + ex.Message);
  106. }
  107. }
  108. public void Close()
  109. {
  110. try
  111. {
  112. serialPort1.Close();
  113. if (thread != null && thread.ThreadState == ThreadState.Running)
  114. {
  115. if (done.WaitOne(500))
  116. {
  117. thread.Suspend();
  118. }
  119. thread.Suspend();
  120. }
  121. receiveBuffer.Clear();
  122. }
  123. catch (System.Exception ex)
  124. {
  125. throw new Exception("关闭串口:" + ex.Message);
  126. }
  127. }
  128. public SerialPort serialPort1;
  129. public List<byte> receiveBuffer = new List<byte>(2046);
  130. private object portLock = new object();
  131. public delegate void MatchedParityHandler(object sender, PortDataEventArgs e);
  132. public event MatchedParityHandler MatchedParity;
  133. private Thread thread;
  134. private void OnMatchedParity(object sender, PortDataEventArgs e)
  135. {
  136. if (MatchedParity != null)
  137. {
  138. MatchedParity(sender, e);
  139. }
  140. }
  141. private class MyData
  142. {
  143. public object sender;
  144. public PortDataEventArgs e;
  145. }
  146. public void OnMatchParity(object o)
  147. {
  148. MyData data = o as MyData;
  149. Console.ForegroundColor = ConsoleColor.Yellow;
  150. //Console.WriteLine("所在线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString() + "类型:" + data.e.type + " " + Byte2HexString(data.e.data));
  151. Console.ResetColor();
  152. OnMatchedParity(data.sender, data.e);
  153. Thread.Sleep(500);//加延时是为了避免解析后有过长的操作占用系统资源
  154. }
  155. public static string Byte2HexString(byte[] buffer)
  156. {
  157. StringBuilder builder = new StringBuilder(buffer.Length * 3);
  158. foreach (byte data in buffer)
  159. {
  160. builder.Append(Convert.ToString(data, 16).PadLeft(2, '0').PadRight(3, ' '));
  161. }
  162. return builder.ToString().ToUpper();
  163. }
  164. private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
  165. {
  166. byte[] buffer = new byte[serialPort1.BytesToRead];
  167. serialPort1.Read(buffer, 0, buffer.Length);
  168. OnReadingData(null);
  169. Console.ForegroundColor = ConsoleColor.Green;
  170. //Console.WriteLine("接收数据:" + Byte2HexString(buffer));
  171. Console.ResetColor();
  172. lock (portLock)
  173. {
  174. receiveBuffer.AddRange(buffer);
  175. }
  176. //Console.WriteLine("缓冲区数据:" + Byte2HexString(receiveBuffer.ToArray()));
  177. }
  178. public static byte XOR_Check(byte[] buffer, int count, int index = 0)
  179. {
  180. byte b = 0;
  181. for (int i = 0; i < count; i++)
  182. {
  183. b ^= buffer[index + i];
  184. }
  185. return b;
  186. }
  187. int endCodeIndex = 8;//尾码索引号
  188. int endCodeCount = 0;//找到尾码的次数
  189. private byte[] DataHander(out int type)
  190. {
  191. type = -1;
  192. int i, j;
  193. if (receiveBuffer.Count >= 9)
  194. {
  195. i = receiveBuffer.FindIndex(0, b => b == 0x10);
  196. if (i != -1)
  197. {
  198. //Console.WriteLine("找到0x10,在位置:{0}", i);
  199. j = receiveBuffer.FindIndex(endCodeIndex, b => b == 0x03);
  200. if (j != -1 && j > i)
  201. {
  202. endCodeIndex = j;
  203. endCodeIndex++;//索引自加
  204. endCodeCount++;
  205. //Console.WriteLine(string.Format("找到0x03,在位置:{0},endcodeIndex={1}", j, endCodeIndex));
  206. if ((j - i + 1) == 10)
  207. {
  208. byte[] tempBuffer = new byte[10];
  209. receiveBuffer.CopyTo(i, tempBuffer, 0, 10);
  210. if (XOR_Check(tempBuffer, 8) == tempBuffer[8])
  211. {
  212. type = 2;
  213. lock (portLock)
  214. {
  215. receiveBuffer.RemoveRange(0, j + 1);
  216. endCodeIndex = 0;//
  217. endCodeCount = 0;
  218. }
  219. return tempBuffer;
  220. }
  221. else
  222. {
  223. //Console.WriteLine(string.Format("没通过校验:{0}", Byte2HexString(tempBuffer)));
  224. lock (portLock)
  225. {
  226. receiveBuffer.RemoveRange(0, j + 1);
  227. }
  228. }
  229. }
  230. else if (receiveBuffer.Count - i > 30)//如果数据长度超过30但校验没通过
  231. {
  232. endCodeIndex = 0;//
  233. endCodeCount = 0;
  234. //Console.WriteLine(string.Format("0x10与0x03间数据过长:", Byte2HexString(receiveBuffer.ToArray())));
  235. lock (portLock)
  236. {
  237. receiveBuffer.RemoveRange(0, j + 1);
  238. }
  239. }
  240. else if (j - i + 1 < 9)
  241. {
  242. //Console.WriteLine(string.Format("找到0x03,但0x03与0x10间数据过短,0x03位置:{0},0x10位置:{1}", j, i));
  243. }
  244. else
  245. {
  246. //Console.WriteLine(string.Format("在找到0x03中没考虑的情况,0x03位置:{0},0x10位置:{1}", j, i));
  247. }
  248. }
  249. else if (j != -1 && j < i)
  250. {
  251. endCodeIndex = 0;//
  252. endCodeCount = 0;
  253. //Console.WriteLine(string.Format("0x03位置:{0}小于0x10位置:{1},数据:{2}", j, i, Byte2HexString(receiveBuffer.ToArray())));
  254. lock (portLock)
  255. {
  256. //receiveBuffer.RemoveAt(i);
  257. receiveBuffer.RemoveRange(0, j + 1);
  258. }
  259. }
  260. else if (/*j == -1 && */receiveBuffer.Count - i > 1000)
  261. {
  262. endCodeIndex = 0;//
  263. endCodeCount = 0;
  264. //Console.WriteLine(string.Format("数据量超过1000:", Byte2HexString(receiveBuffer.ToArray())));
  265. lock (portLock)
  266. {
  267. //receiveBuffer.RemoveAt(i);
  268. receiveBuffer.RemoveRange(0, receiveBuffer.Count);
  269. }
  270. }
  271. else
  272. {
  273. //Console.WriteLine(string.Format("没考虑到情况,可能找到0x03,0x10位置:{0},0x03位置:{1},数据:{2}", Byte2HexString(receiveBuffer.ToArray())));
  274. }
  275. }
  276. else
  277. {
  278. //Console.WriteLine(string.Format("0x10没找到:", Byte2HexString(receiveBuffer.ToArray())));
  279. lock (portLock)
  280. {
  281. receiveBuffer.RemoveRange(0, receiveBuffer.Count);
  282. }
  283. }
  284. }
  285. return new byte[1] { 0 };
  286. }
  287. AutoResetEvent done = new AutoResetEvent(true);//在处理数据的时候不允许被打断(只有在线程正常挂起时有效)
  288. public void ThreadHandler()
  289. {
  290. while (true)
  291. {
  292. if (serialPort1.IsOpen)
  293. {
  294. //Console.WriteLine("分析线程运行中...");
  295. if (receiveBuffer.Count > 0)
  296. {
  297. done.Reset();
  298. byte[] buffer;
  299. int type;
  300. buffer = DataHander(out type);
  301. PortDataEventArgs e = new PortDataEventArgs();
  302. e.type = type;
  303. e.data = buffer;
  304. if (type != -1)
  305. {
  306. MyData data = new MyData();
  307. data.sender = this;
  308. data.e = e;
  309. Thread t = new Thread(OnMatchParity);
  310. t.Start(data);
  311. //OnMatchedParity(this, e);
  312. Console.ForegroundColor = ConsoleColor.Blue;
  313. //Console.WriteLine("类型:" + type.ToString() + " " + Byte2HexString(buffer));
  314. Console.ResetColor();
  315. }
  316. }
  317. }
  318. Thread.Sleep(10);
  319. done.Set();
  320. }
  321. }
  322. }
  323. internal class PortDataEventArgs : EventArgs
  324. {
  325. public byte[] data;
  326. public int type;
  327. }
  328. }