Files
Desktop_485BurningTool/Transmitter/SerialController.vb
2025-12-11 10:09:40 +08:00

537 lines
19 KiB
VB.net

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
''' <summary>
''' 接收数据缓存包
''' </summary>
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