Imports System.IO.Ports Imports System.Threading Imports _485_BurningTool.BLV_Bootloader Public Class SerialController Inherits Transmitter Public m_Serial As SerialPort Public m_SerialComfig As SerialComfig Public m_Control As Control Private Timer1 As System.Windows.Forms.Timer '接收数据队列 Public m_ReceiveQueue As List(Of Cmdconfig) = New List(Of Cmdconfig) '特殊接收处理标志 Public m_SpecialReceiveFlag As Integer Sub New(gControl As Control) CommunicationTypeindex = 1 m_SerialComfig = New SerialComfig m_ReceiveQueue = New List(Of Cmdconfig) m_ReceiveQueue.Clear() m_Control = gControl 'm_Serial = New SerialPort 'CreateSerial(m_SerialComfig) '创建定时器绑定定时器函数 'Timer1 = New System.Windows.Forms.Timer 'Timer1.Interval = 1000 'AddHandler Timer1.Tick, AddressOf TimerTick 'Timer1.Start() recvBufferli = New List(Of Byte) m_SpecialReceiveFlag = -1 End Sub '定时器函数 定时查看接收队列是否接收超时 Public Sub TimerTick() Dim len As Integer = m_ReceiveQueue.Count For i = 0 To len - 1 '从尾部倒序查看节点是否超时 Dim item As Cmdconfig = m_ReceiveQueue(len - 1 - i) If (Now - item.CmdSendTime).TotalSeconds > item.CmdReceiveTimeout Then m_ReceiveQueue.RemoveAt(len - 1 - i) End If Next End Sub '创建串口连接 Public Function CreateSerial(g_SerialComfig As SerialComfig) As Boolean Try If IsNothing(m_Serial) Then m_Serial = New SerialPort(g_SerialComfig.PortName, g_SerialComfig.BaudRate, g_SerialComfig.Parity, g_SerialComfig.DataBits, g_SerialComfig.StopBits) AddHandler m_Serial.DataReceived, AddressOf DataReceivedHandler m_Serial.Open() Return True Else Dim m_SerialIsOpen As Boolean = False If m_Serial.IsOpen Then isread = True While isListen Application.DoEvents() Thread.Sleep(10) End While Thread.Sleep(10) m_Serial.Close() m_SerialIsOpen = True End If m_Serial.PortName = g_SerialComfig.PortName m_Serial.BaudRate = g_SerialComfig.BaudRate m_Serial.Parity = g_SerialComfig.Parity m_Serial.DataBits = g_SerialComfig.DataBits m_Serial.StopBits = g_SerialComfig.StopBits m_Serial.Handshake = g_SerialComfig.Handshake If m_SerialIsOpen Then m_Serial.Open() End If End If Catch ex As Exception Return False End Try Return True End Function Public Overrides Sub ClearReadData() If IsNothing(m_Serial) Then Return Else If m_Serial.IsOpen Then '清空接收缓存 m_Serial.DiscardInBuffer() End If End If If IsNothing(recvBufferli) OrElse recvBufferli.Count = 0 Then Return Else recvBufferli.Clear() End If End Sub '设置串口参数 ''' 接收数据偏移量 Private _recvOffset, _recvstar As Integer ''' ''' 接收数据缓存包 ''' Private _recvBuffer(4095) As Byte Public recvBufferli As List(Of Byte) Public recvBufferliindex As Integer = 0 '获取 串口数据 Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs) If isread Then Return isListen = True Static bytes As Integer = 0 Dim sp As SerialPort = DirectCast(sender, SerialPort) Try Select Case m_SpecialReceiveFlag Case WorkflowType.SearchEquipment Do bytes = sp.BytesToRead If bytes <= 0 Then isListen = False Exit Sub End If 'If bytes + _recvOffset >= 4096 Then ' 'ShowPortReceData(_recvBuffer) ' sp.Read(_recvBuffer, _recvOffset, 4096 - _recvOffset) ' _recvOffset = 0 'Else ' sp.Read(_recvBuffer, _recvOffset, bytes) ' _recvOffset += bytes 'End If Dim buf(bytes - 1) As Byte sp.Read(buf, 0, bytes) recvBufferli.AddRange(buf) Thread.Sleep(1) Loop While sp.BytesToRead > 0 If recvBufferli.Count > 0 Then 'RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"RX:{DataProcessing.ByteToString2(recvBufferli.ToArray)}", Color.Black), 1) Dim item As Cmdconfig item = m_ReceiveQueue(0) '判断超时 If item.CmdSendTime.AddMilliseconds(item.CmdReceiveTimeout) < Now Then recvBufferli.Clear() recvBufferliindex = 0 Console.WriteLine("超时清空-----------------------------") Else '截取搜索回复 recvBufferliindex = ExtractSearchReply(recvBufferli.ToArray, item) End If End If Case Else Do bytes = sp.BytesToRead If bytes <= 0 Then isListen = False Exit Sub End If 'If bytes + _recvOffset >= 4096 Then ' 'ShowPortReceData(_recvBuffer) ' sp.Read(_recvBuffer, _recvOffset, 4096 - _recvOffset) ' _recvOffset = 0 'Else ' sp.Read(_recvBuffer, _recvOffset, bytes) ' _recvOffset += bytes 'End If Dim buf(bytes - 1) As Byte sp.Read(buf, 0, bytes) '清空可读缓存 'sp.DiscardInBuffer() recvBufferli.AddRange(buf) Thread.Sleep(7) Loop While sp.BytesToRead > 0 If recvBufferli.Count > 0 Then Dim buf(recvBufferli.Count - 1) As Byte Array.Copy(recvBufferli.ToArray, 0, buf, 0, buf.Length) recvBufferli.Clear() ' Array.Copy(_recvBuffer, _recvstar, buf, 0, buf.Length) 'Console.WriteLine(DataProcessing.ByteToString2(buf)) '_recvstar = _recvOffset '枚举队列 '获取队列第5个元素 Dim len As Integer = m_ReceiveQueue.Count Dim item As Cmdconfig Dim timep As TimeSpan ' RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"RX:{DataProcessing.ByteToString2(buf)}", Color.Blue), 1) mCommunicationFlowAddQueue(m_Control, New RuningLogConfig($"RX:{DataProcessing.ByteToString2(buf)}", Color.Blue), 1) ' ' RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"RX:{DataProcessing.ByteToString2(buff)}", Color.Blue), 1) 'Console.WriteLine($"RX():{len} ") For i = 0 To len - 1 ' Console.WriteLine($"RX:{len - 1 - i}< {m_ReceiveQueue.Count }") If (len - 1 - i) < m_ReceiveQueue.Count Then item = m_ReceiveQueue(len - 1 - i) 'timep = (Now - item.CmdSendTime) ''判断本节点接收时间是否超时 'If item.CmdReceiveStatus OrElse timep.TotalSeconds > item.CmdReceiveTimeout Then ' Console.WriteLine($"item.CmdReceiveStatus:{item.CmdReceiveStatus}, timep.TotalSeconds > item.CmdReceiveTimeout :{ timep.TotalSeconds}>{item.CmdReceiveTimeout}") ' item.setCmdReceiveStatus(True) ' Continue For 'End If '按照对应协议解析 并设置到本节点中 item.Protocol.ParseReceiveData(item, buf) End If Next End If End Select isListen = False Catch ex As Exception isListen = False 'AppendTipText($"串口接收数据失败,原因:{ex.Message}", Color.Red) RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"串口接收数据失败,原因:{ex.Message}", Color.Red), 1) End Try End Sub Delegate Sub delmCommunicationFlowAddQueue(c As Control, rl As RuningLogConfig, lev As Integer) Public Sub mCommunicationFlowAddQueue(c As Control, rl As RuningLogConfig, Optional lev As Integer = 0) If c.InvokeRequired Then Dim d As New delmCommunicationFlowAddQueue(AddressOf mCommunicationFlowAddQueue) c.Invoke(d, c, rl, lev) Else RuningLog.OutputLogsToTheControl(c, rl, lev) End If End Sub Public Function ExtractSearchReply(bufarry As Byte(), item As Cmdconfig) As Integer If bufarry.Length - recvBufferliindex < 12 Then RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"接收数据长度异常!", Color.Red), 1) Return recvBufferliindex End If Dim len As Integer Dim result As Integer = recvBufferliindex 'Dim buff(44) As Bytei+ '遍历找到sn\ ' Console.WriteLine($"ExtractSearchReply:{recvBufferliindex} {vbCrLf}RX:{DataProcessing.ByteToString2(bufarry)}") AddQueue(m_Control, New RuningLogConfig($"RX1:", Color.Blue), 1) For i = recvBufferliindex To bufarry.Length - 1 If (bufarry(i) And &HF) = (item.CmdSendData(1) And &HF) Then ' If i + 6 < bufarry.Length Then If bufarry(i + 2) = item.CmdSendData(0) AndAlso bufarry(i + 6) = item.CmdSendData(7) Then len = bufarry(i + 3) + bufarry(i + 4) * 256 Dim buff(len - 1) As Byte If i > 0 Then If i + len - 2 < bufarry.Length Then Try Array.Copy(bufarry, i - 1, buff, 0, len) i = i + len - 2 item.Protocol.ParseReceiveData(item, buff) result = i + 1 AddQueue(m_Control, New RuningLogConfig($"RX2:", Color.Blue), 1) '{DataProcessing.ByteToString2(buff)} ' RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"RX:{DataProcessing.ByteToString2(buff)}", Color.Blue), 1) Catch ex As Exception MsgBox(ex.Message) End Try End If Else End If End If End If End If Next Console.WriteLine($"ExtractSearchReply------end:{result}") Return result End Function '设置波特率 Public Sub AnalyzeData() End Sub '判断串口是否有数据未接收 Public Function IsSerialData() As Boolean ' If IsNothing(m_Serial) Then Return False Return m_Serial.BytesToRead > 0 End Function Public Function SetBaudRate(baudRate As Integer, Optional devnumber As Integer = 1) As Boolean If IsNothing(m_Serial) Then Return False Dim ret As Boolean = m_Serial.IsOpen 'Dim buff As Byte() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25} If m_Serial.IsOpen Then 'Thread.Sleep(300 * devnumber) isread = True While isListen Application.DoEvents() Thread.Sleep(10) End While Thread.Sleep(10) 'm_Serial.Write(buff, 0, buff.Length) m_Serial.Close() End If m_Serial.BaudRate = baudRate If ret Then isread = False m_Serial.Open() 'm_Serial.Write(buff, 0, buff.Length) End If Return True End Function '打开串口 Public Function OpenSerial() As Boolean If IsNothing(m_Serial) Then Return False If Not m_Serial.IsOpen Then isread = False m_Serial.Open() End If End Function '关闭串口连接 Public Sub CloseSerial() If IsNothing(m_Serial) Then Return If m_Serial.IsOpen Then isread = True While isListen Application.DoEvents() Thread.Sleep(10) End While Thread.Sleep(10) m_Serial.Close() End If Timer1.Stop() End Sub '获取串口接收数据 Public Overrides Function ReceiveData(g_comfig As Cmdconfig) As Cmdconfig End Function '发送数据 Public Overrides Sub SendData(data As Cmdconfig) data.CmdSendTime = DateTime.Now If IsNothing(m_Serial) OrElse Not m_Serial.IsOpen Then RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"发送器未连接!", Color.Red), 1) Return End If 'Dim Rl As New RuningLogConfig($"TX:", Color.DarkGreen) 'Rl.strdata = data.CmdSendData ' RuningLog.OutputLogsToTheControl(m_Control, Rl, 1) 'AddQueue(m_Control, New RuningLogConfig($"TX:", Color.DarkGreen), 1) '清空发送缓存 'm_Serial.DiscardOutBuffer() Try m_Serial.Write(data.CmdSendData, 0, data.CmdSendData.Length) 'Dim buff As Byte() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25} 'm_Serial.Write(buff, 0, buff.Length) Catch ex As Exception Console.WriteLine(ex.Message) End Try End Sub Public Overrides Function OpenTransmitter() As Boolean If IsNothing(m_Serial) Then Return CreateSerial(m_SerialComfig) End If If Not m_Serial.IsOpen Then Try isread = False m_Serial.Open() Catch ex As Exception Return False End Try End If Return True End Function Public isread As Boolean = False Public isListen As Boolean = False Public Overrides Sub CloseTransmitter() If IsNothing(m_Serial) OrElse Not m_Serial.IsOpen Then Return isread = True While isListen Application.DoEvents() Thread.Sleep(10) End While Thread.Sleep(10) m_Serial.Close() m_Serial = Nothing End Sub Public Overrides Function IsTransmitter() As Boolean If IsNothing(m_Serial) Then Return False Else Return True End If End Function Public Overrides Function GetTransmitterStatus() As Boolean If IsNothing(m_Serial) Then Return False Return m_Serial.IsOpen End Function ' Public Overrides Function SetTransmitterParameter(ParamArray params() As Object) As Boolean If IsNothing(m_SerialComfig) Then Return False 'If m_Serial.IsOpen Then m_Serial.Close() If params.Length > 0 Then If TypeOf params(0) Is String Then m_SerialComfig.PortName = params(0) End If End If If params.Length > 1 Then If TypeOf params(1) Is Integer Then m_SerialComfig.BaudRate = params(1) End If End If If params.Length > 2 Then If TypeOf params(2) Is Integer Then m_SerialComfig.DataBits = params(2) End If End If If params.Length > 3 Then If TypeOf params(3) Is Parity Then m_SerialComfig.Parity = params(3) End If End If If params.Length > 4 Then If TypeOf params(4) Is StopBits Then m_SerialComfig.StopBits = params(4) End If End If If params.Length > 5 Then If TypeOf params(5) Is Handshake Then m_SerialComfig.Handshake = params(5) End If End If Return CreateSerial(m_SerialComfig) End Function Public Overrides Sub ClearSendData() If IsNothing(m_ReceiveQueue) Then Return m_ReceiveQueue.Clear() End Sub Public Overrides Function SendData(data() As Byte) As Boolean 'data.CmdSendTime = DateTime.Now If IsNothing(m_Serial) OrElse Not m_Serial.IsOpen Then RuningLog.OutputLogsToTheControl(m_Control, New RuningLogConfig($"发送器未连接!", Color.Red), 1) Return False End If 'Dim Rl As New RuningLogConfig($"TX:", Color.DarkGreen) 'Rl.strdata = data.CmdSendData ' RuningLog.OutputLogsToTheControl(m_Control, Rl, 1) 'AddQueue(m_Control, New RuningLogConfig($"TX:", Color.DarkGreen), 1) '清空发送缓存 'm_Serial.DiscardOutBuffer() Try m_Serial.Write(data, 0, data.Length) 'Dim buff As Byte() = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25} 'm_Serial.Write(buff, 0, buff.Length) Catch ex As Exception Console.WriteLine(ex.Message) Return False End Try Return True End Function End Class Public Class SerialComfig '串口名称 Public PortName As String '波特率 Public BaudRate As Integer '数据位 Public DataBits As Integer '校验位 Public Parity As Parity '停止位 Public StopBits As StopBits '流控制 Public Handshake As Handshake '获取 串口名称列表 Sub New() PortName = GetPortNames()(0) BaudRate = GetBaudRates()(0) DataBits = 8 Parity = Parity.None StopBits = StopBits.One Handshake = Handshake.None End Sub Public Shared Function GetPortNames() As String() Return SerialPort.GetPortNames() End Function '获取波特率列表 Public Shared Function GetBaudRates() As Integer() Return New Integer() {300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000, 256000, 512000} End Function End Class