C# 在Linux系统使用串口通讯
1. NuGet上安装 flyfire.CustomSerialPort

2. 串口类
public class serialPort { public byte Lo; public byte Hi; public SerialPort Comm = new SerialPort(); public bool Open() { try { Comm.Open(); return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } } public bool Close() { try { Comm.Close(); return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } } public bool Setting(string Name, int BaudRate, int DataBits, int StopBits, int ReadTimeout) { try { if (Comm.IsOpen == true) Comm.Close(); Comm.PortName = Name; Comm.BaudRate = BaudRate; //波特率设置 Comm.DataBits = DataBits; //数据位设置 Comm.StopBits = (StopBits)StopBits; //停止位设置 Comm.Parity = Parity.None; return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } } public delegate void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e); private object WriteLock = new object(); public bool WriteBinary(byte[] value) { try { if (Comm.IsOpen == false) Comm.Open(); //int i = Comm.BytesToWrite; lock (WriteLock) { Comm.Write(value, 0, value.Length); } return true; } catch (Exception ex) { Console.WriteLine(ex.ToString()); return false; } } /// <summary> /// 延时读取全部 /// </summary> /// <param name="Timeout">延时时间</param> /// <returns></returns> public byte[] ReadBinary(int sleep) { try { if (Comm.IsOpen == false) Comm.Open(); Thread.Sleep(sleep); byte[] data = new byte[Comm.BytesToRead]; Comm.Read(data, 0, data.Length); return data; } catch (Exception) { return null; } } /// <summary> /// 等待读取固定字节数 /// </summary> /// <param name="readNum">读取字节数</param> /// <param name="a"></param> /// <returns></returns> public byte[] ReadBinaryA(int readNum) { try { if (Comm.IsOpen == false) Comm.Open(); while (Comm.BytesToRead <= readNum) { Thread.Sleep(1); } //Thread.Sleep(Timeout); byte[] data = new byte[readNum]; Comm.Read(data, 0, data.Length); return data; } catch (Exception) { return null; } } /// <summary> /// 轮询缓存区状态读取数据 /// </summary> /// <param name="readNum"></param> /// <returns></returns> public byte[] ReadBinaryB() { try { if (Comm.IsOpen == false) Comm.Open(); int count = -1; while (Comm.BytesToRead != count) { Thread.Sleep(1); if (Comm.BytesToRead != 0) { count = Comm.BytesToRead; } } byte[] data = new byte[count]; Comm.Read(data, 0, data.Length); return data; } catch (Exception) { return null; } } public byte[] ReadBinaryTimeout(int number) { try { if (Comm.IsOpen == false) Comm.Open(); byte[] data = new byte[number]; try { DateTime starttime = DateTime.Now; Thread.Sleep(200); Comm.Read(data, 0, data.Length); } catch (Exception) { } return data; } catch (TimeoutException) { byte[] data = new byte[Comm.BytesToRead]; Comm.Read(data, 0, Comm.BytesToRead); return data; } } public byte[] Chr_crc(byte[] data, int Index) { int len = data.Length - Index; if (len > 0) { ushort crc = 0xFFFF; for (int i = 0; i < len; i++) { crc = (ushort)(crc ^ (data[i])); for (int j = 0; j < 8; j++) { crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1); } } Hi = (byte)((crc & 0xFF00) >> 8); //高位置 Lo = (byte)(crc & 0x00FF); //低位置 return new byte[] { Hi, Lo }; } return null; } /// <summary> /// 检验异或校验 /// </summary> /// <param name="Buffer"></param> /// <param name="len"></param> /// <returns></returns> public int BCC_Xor_Check(byte[] Buffer, int len) { int Xor = 0; int i; for (i = 0; i < len - 1; i++) Xor = Xor ^ Buffer[i]; if (Buffer[len - 1] == Xor) return 1; else return 0; } /// <summary> /// 添加异或校验 /// </summary> /// <param name="Buffer"></param> /// <param name="len"></param> public void BCC_Xor_Write(byte[] Buffer, int len) { int Xor = 0; int i; for (i = 0; i < len - 1; i++) Xor = Xor ^ Buffer[i]; Buffer[len - 1] = (byte)Xor; } public static byte[] CalculateAdd(byte[] buffer, int start, int length)//取低八位 { int cks = 0; for (int i = start; i < length; i++) { cks = (cks + buffer[i]) % 0xffff; } byte Hi = (byte)((cks & 0xff00) >> 8);//取校验和高8位 byte Lo = (byte)(cks & 0xff);//取校验和低8位 return new byte[] { Lo, Hi }; } }
3. 调用(简单的只需要关注<comm>对象就行)
static serialPort comm = new serialPort(); // 打开串口 public static rth_OpenSerialPort OpenSerialPort(string JsonString) { try { OpenSerialPort json = JsonHelper.DeserializeJsonToObject<OpenSerialPort>(JsonString); if (json == null) throw new System.Exception("json解析失败!"); rth_OpenSerialPort rth = new rth_OpenSerialPort(); // $"/dev/{json.PortName}" if (comm.Comm.IsOpen) { rth.IsOpen = true; return rth; } comm.Setting(json.PortName, json.BaudRate, 8, 1, 200); rth.IsOpen = comm.Open(); if (rth.IsOpen && (upCTS == null)) { MessageReceived(); SendSerialPort(); Thread.Sleep(1000); } return rth; } catch (Exception ex) { Logger.Error("OpenSerialPort:" + ex.Message); return new rth_OpenSerialPort() { IsOpen = false }; } } // 关闭串口 public static rth_CloseSerialPort CloseSerialPort(string JsonString) { try { CloseSerialPort json = JsonHelper.DeserializeJsonToObject<CloseSerialPort>(JsonString); if (json == null) throw new System.Exception("json解析失败!"); rth_CloseSerialPort rth = new rth_CloseSerialPort(); if (upCTS != null) upCTS.Cancel(); Thread.Sleep(1000); rth.IsClose = comm.Close(); return rth; } catch (Exception ex) { Logger.Error("CloseSerialPort:" + ex.Message); return new rth_CloseSerialPort() { IsClose = false }; } } // 接收数据 static CancellationTokenSource upCTS; public static void MessageReceived() { upCTS = new CancellationTokenSource(); Task.Run(() => { while (!upCTS.Token.IsCancellationRequested) { try { BasicDataModel a = new BasicDataModel(); byte[] bytes = null; // 电压电流量程 lock (SendLock) { comm.WriteBinary(new byte[] { 0x01, 0x03, 0x04, 0x14, 0x00, 0x03, 0x44, 0xFF }); bytes = comm.ReadBinary(200); } if (bytes != null && bytes.Length > 0) { //a.voltageRange = (bytes[4]).ToString(); //a.currentRange = (bytes[6]).ToString(); a.outEnergyModel = (bytes[8]).ToString(); } lock (Lock_M) { MonitorData = a; } } catch (Exception ex) { Logger.Error("MessageReceived:" + ex.Message); Console.WriteLine(ex.ToString()); } } upCTS = null; }); } public static object Lock_M { get; set; } = new object(); public static BasicDataModel MonitorData { get; set; } = new BasicDataModel(); // 发送数据 public static object SendLock { get; set; } = new object(); public static object SDLock { get; set; } = new object(); public static List<byte[]> SendDatas { get; set; } = new List<byte[]>(); static CancellationTokenSource sendCTS { get; set; } public static void SendSerialPort() { sendCTS = new CancellationTokenSource(); Task.Run(() => { while (!sendCTS.Token.IsCancellationRequested) { try { List<byte[]> senddata = new List<byte[]>(); lock (SDLock) { senddata.AddRange(SendDatas); SendDatas.Clear(); } foreach (byte[] data in senddata) { lock (SendLock) { comm.WriteBinary(data); comm.ReadBinary(200); } } Thread.Sleep(500); } catch (Exception ex) { Logger.Error("SendSerialPort:" + ex.Message); } } }); }
浙公网安备 33010602011771号