using BaseLibRWFile; using HardwareConfig; using System; using System.Collections.Generic; using System.IO.Ports; using System.Text; using System.Threading; using System.Windows.Forms; namespace BaseLibComm { public class StSerialPort { public int Index; public bool Enable; public string Name; public SerialPort serialPort;//= new SerialPort(); public byte[] byteReceiveData; public string strReceivCommandData; public string strSendCommandData; public string strRecv; public int CurrentAddr = 0; public bool[,] BitVaueArray = new bool[16, 256]; public bool[] bComRunNomalFlag = new bool[16]; public short[,] WordValueArray = new short[16, 256]; public bool comBusying; public bool isOpen = false; public SeriesTypeEnum SeriesType; public Action RevDataAction; } public class SerialPortManager { public static SerialPortManager Ins = new SerialPortManager(); public static Dictionary DicSerialPort { set; get; } = new Dictionary { }; //private bool bCommWell; private readonly System.Timers.Timer tmrTimeOut = new System.Timers.Timer(500);//实例化Timer类,设置间隔时间为10000毫秒; public SerialPortManager() { } public void LoadSerialProt() { //StSerialPort st = new StSerialPort(); foreach (var p in HardConfigManager.Ins.HardwareList) { if (p.Enable) { switch (p.HardwareName) { case HardwareNameEnum.串口: SeriesAtti series = (SeriesAtti)p; StSerialPort st = new StSerialPort { Index = series.编号, Enable = true, Name = series.串口名称, SeriesType = series.串口类型, serialPort = new SerialPort { BaudRate = Convert.ToInt32(series.波特率.ToString().Remove(0, 1)),//B115200 PortName = series.端口号.ToString(), DataBits = series.数据位, Parity = series.校验位, StopBits = series.停止位 } }; DicSerialPort.Add(st.serialPort.PortName, st); break; default: break; } } } } public bool OpenSerialPort(StSerialPort st) { bool bResult = false; switch (st.SeriesType) { case SeriesTypeEnum.RS232: bResult = OpenGeneralSerialPort(st); break; case SeriesTypeEnum.RS485: bResult = OpenGeneralSerialPort(st); break; case SeriesTypeEnum.ModbusRTU: bResult = ModbusRTU.Ins.OpenMyCom(st); break; case SeriesTypeEnum.ModbusACSII: bResult = ModbusRTU.Ins.OpenMyCom(st); break; } return bResult; } private bool OpenGeneralSerialPort(StSerialPort st) { try { //先关闭已经打开的串口 if (st.serialPort.IsOpen) { st.serialPort.Close(); } st.serialPort.ReceivedBytesThreshold = 1; st.serialPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);//DataReceived事件委托 //打开串口 st.serialPort.Open(); //设置超时定时器属性 tmrTimeOut.Elapsed += new System.Timers.ElapsedEventHandler(SerialPortTimeOut);//到达时间的时候执行事件; tmrTimeOut.AutoReset = true;//设置超时是执行一次(false)还是一直执行(true); tmrTimeOut.Enabled = false;//是否执行System.Timers.Timer.Elapsed事件; //comBusying = false; //bCommWell = false; st.isOpen = true;// ;st.serialPort.IsOpen return true; } catch (Exception ex) { string str = $"{st.serialPort.PortName}串口打开失败:"; Msg.Show($"{str}\r\n{ex}", $"{str}\r\nFailed to open the serial port:\r\n{ex}", "Error", msgicon: MessageBoxIcon.Error); //MessageBox.Show($"{st.serialPort.PortName}串口打开失败\r\nFailed to open the serial port\r\n{ex.Message }", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } finally { } } public void CloseSerialPort(StSerialPort st) { try { st.isOpen = false; st.serialPort.Close(); } catch (Exception) { throw; } } //DataReceived事件委托方法 每个协议都需重写DataReceived public void ReceiveData(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = sender as SerialPort; try { if (DicSerialPort[sp.PortName].serialPort.BytesToRead > 0) { DicSerialPort[sp.PortName].strRecv = string.Empty; Thread.Sleep(50); DicSerialPort[sp.PortName].byteReceiveData = new byte[DicSerialPort[sp.PortName].serialPort.BytesToRead]; DicSerialPort[sp.PortName].serialPort.Read(DicSerialPort[sp.PortName].byteReceiveData, 0, DicSerialPort[sp.PortName].byteReceiveData.Length); DicSerialPort[sp.PortName].RevDataAction?.Invoke(DicSerialPort[sp.PortName].byteReceiveData); DicSerialPort[sp.PortName].strRecv = Encoding.ASCII.GetString(DicSerialPort[sp.PortName].byteReceiveData,0, DicSerialPort[sp.PortName].byteReceiveData.Length); } } catch (Exception ex) { MessageBox.Show($"{DicSerialPort[sp.PortName].serialPort.PortName}串口接收数据错误\r\nSerial port received data error\r\n{ex.Message }", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public bool SendData(StSerialPort st, string strData) { try { if (st.serialPort.IsOpen) { st.serialPort.DiscardOutBuffer();//清除缓冲区里的内容 st.serialPort.DiscardInBuffer(); st.serialPort.Write(strData); return true; } else { return false; } } catch (Exception ex) { MessageBox.Show($"{st.serialPort.PortName}发送数据失败\r\nFailed to send data\r\n{ex.Message}", "Error"); return false; } } public bool SendData(StSerialPort st, byte[] strData) { try { if (st.serialPort.IsOpen) { st.serialPort.DiscardOutBuffer();//清除缓冲区里的内容 st.serialPort.DiscardInBuffer(); st.serialPort.Write(strData,0, strData.Length); return true; } else { return false; } } catch (Exception ex) { MessageBox.Show($"{st.serialPort.PortName}发送数据失败\r\nFailed to send data\r\n{ex.Message}", "Error"); return false; } } //定时器超时事件 public void SerialPortTimeOut(object source, System.Timers.ElapsedEventArgs e) { //if (bCommWell == false) //{ // //bComRunNomalFlag[CurrentAddr] = true;//设置本地址通讯故障 // //strReceivCommandData = ""; //} //tmrTimeOut.Enabled = false; //comBusying = false;//设置串口忙标志 } } }