- #Region "属性和结构"
-
- ''' <summary>
- ''' Modbus通讯模块是以这个命令结构来传递命令和数据的。本命令结构包含了Modbus通讯所需要的各种数据。
- ''' </summary>
- ''' <remarks></remarks>
- Public Structure stCommand
- ''' <summary>
- ''' 当模块为Modbus主站,向从站发送命令时,本参数记录需要接收命令的从站地址。
- ''' 当模块为从站,本参数记录本站地址
- ''' </summary>
- ''' <remarks></remarks>
- Public AddressOfReceive As Byte
-
- ''' <summary>
- ''' 命令代码
- ''' </summary>
- ''' <remarks></remarks>
- Public Command As enCommandType
-
- ''' <summary>
- ''' 读数据偏置量
- ''' </summary>
- ''' <remarks></remarks>
- Public ReadAddress As UInt16
-
- ''' <summary>
- ''' 读数据单位总数
- ''' </summary>
- ''' <remarks></remarks>
- Public ReadCount As UInt16
-
- ''' <summary>
- ''' 写数据偏置量
- ''' </summary>
- ''' <remarks></remarks>
- Public WriteAddress As UInt16
-
- ''' <summary>
- ''' 写数据单位总数
- ''' </summary>
- ''' <remarks></remarks>
- Public WriteCount As UInt16
-
- ''' <summary>
- ''' 数据字节数
- ''' </summary>
- ''' <remarks></remarks>
- Public DataLen As UInt16
-
- ''' <summary>
- ''' 数据数组
- ''' </summary>
- ''' <remarks></remarks>
- Public Data() As Byte
- End Structure
-
- ''' <summary>
- ''' 通讯状态
- ''' </summary>
- ''' <remarks></remarks>
- Public Structure stState
- ''' <summary>
- ''' 通讯正常或故障状态
- ''' </summary>
- ''' <remarks></remarks>
- Public PortState As enCommStateType
-
- ''' <summary>
- ''' 通讯时所处的过程阶段状态
- ''' </summary>
- ''' <remarks></remarks>
- Public WorkState As enWorkStateType
-
- ''' <summary>
- ''' 通讯信息
- ''' </summary>
- ''' <remarks></remarks>
- Public Msg As String
- End Structure
-
- ''' <summary>
- ''' 读取、设置串口波特率
- ''' </summary>
- ''' <value>[in]波特率只能为 9600、19200、38400 。</value>
- ''' <returns>返回当前波特率</returns>
- ''' <remarks>波特率只能为 9600、19200、38400。</remarks>
- Public Property m_iBaudRate() As Long
- Get
- Return SerialPort1.BaudRate
- End Get
- Set(ByVal Value As Long)
- Select Case Value
- Case 9600, 19200, 38400
- SerialPort1.BaudRate = Value
- Case Else
- SerialPort1.BaudRate = 9600
- End Select
- End Set
- End Property
-
- ''' <summary>
- ''' 设置、读取串口号
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks>可通过GetSerialPortNames获取所有的串口名称</remarks>
- Public Property m_strPortName() As String
- Get
- Return SerialPort1.PortName
- End Get
- Set(ByVal Value As String)
- Try
- SerialPort1.Close()
- Catch ex As Exception
-
- End Try
-
- Try
- SerialPort1.PortName = Value
- SerialPort1.Open() '需要保持串口一直打开
- Catch ex As Exception
- MsgBox(ex.ToString)
- End Try
- End Set
- End Property
-
- Private enModbusMaster As enMasterType
- ''' <summary>
- ''' 设置、返回串口通讯PC机所扮演的主从角色
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks>
- ''' 角色为主,则需要承担通讯的发起者的角色,接收数据不需要回应。
- ''' 角色为从,则没有主动发出信息的权利,只有当通讯的主节点要求时才能发送数据,对于主节点的命令需要回复
- ''' </remarks>
- Public Property m_enModbusMaster() As enMasterType
- Get
- Return enModbusMaster
- End Get
- Set(ByVal Value As enMasterType)
- Try
- enModbusMaster = Value
- m_State.WorkState = enWorkStateType.Idle
- m_State.PortState = enCommStateType.Normal
- m_State.Msg = ""
- Catch ex As Exception
- MsgBox(ex.ToString)
- End Try
- End Set
- End Property
-
- ''' <summary>
- ''' Modbus通讯状态
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public ReadOnly Property m_ModbusState() As stState
- Get
- Return m_State
- End Get
- End Property
- #End Region
-
- #Region "CRC 字节值表"
- ' CRC 高位字节值表
- Private auchCRCHi() As Byte = New Byte() { _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _
- &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _
- &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _
- &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _
- &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _
- &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _
- &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _
- &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _
- &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _
- &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _
- &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _
- &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _
- &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _
- &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _
- &H80, &H41, &H0, &HC1, &H81, &H40}
-
- ' CRC低位字节值表
- Private auchCRCLo() As Byte = New Byte() { _
- &H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, _
- &H7, &HC7, &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HCD, _
- &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, &H9, _
- &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, _
- &H1E, &HDE, &HDF, &H1F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, _
- &HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, _
- &H11, &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, _
- &HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, &H35, &H34, &HF4, _
- &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, _
- &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, _
- &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, _
- &HEC, &H2C, &HE4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, _
- &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, _
- &H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, _
- &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, _
- &H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, _
- &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, _
- &H7F, &HBF, &H7D, &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, _
- &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, _
- &H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, _
- &H96, &H56, &H57, &H97, &H55, &H95, &H94, &H54, &H9C, &H5C, _
- &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, _
- &H99, &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, _
- &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, _
- &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, _
- &H43, &H83, &H41, &H81, &H80, &H40}
-
- #End Region
-
- '获得组件对象
- Private TimerOp As New System.Timers.Timer
- Private SerialPort1 As New System.IO.Ports.SerialPort
-
- '命令结构
- Private m_Cmd As New stCommand
- Private m_State As New stState
-
- '输入输出暂存
- Private uchCRCHi As Byte = &HFF ' 高CRC字节初始化
- Private uchCRCLo As Byte = &HFF '低CRC 字节初始化
-
- ''' <summary>
- ''' 通讯结束时发出的消息
- ''' </summary>
- ''' <param name="stCmd">[in/out]包含通讯命令所有信息的命令结构</param>
- ''' <remarks></remarks>
- Public Event CommunicationOverEvent(ByVal stCmd As stCommand, ByVal stState As stState)
-
- ''' <summary>
- ''' 输入通讯节点地址, 对串口和时钟进行初始化
- ''' </summary>
- ''' <param name="BusAddress">[in]节点地址</param>
- ''' <param name="MasterOrSlaver">[in]节点主从设置</param>
- ''' <param name="OutTimeSetting">[in]通讯超时设置</param>
- ''' <param name="PortName">[in]模块使用的串口名称</param>
- ''' <remarks></remarks>
- Public Sub New(ByVal BusAddress As Byte, ByVal MasterOrSlaver As enMasterType, ByVal PortName As String, ByVal OutTimeSetting As Int16)
-
- '设置时钟超时参数
- TimerInit(OutTimeSetting)
-
- '设置Modbus主从模式
- enModbusMaster = MasterOrSlaver
-
- '设置Modbus节点地址
- If enModbusMaster = enMasterType.Slaver Then
- m_Cmd.AddressOfReceive = BusAddress
- End If
-
- '初始化Modbus工作状态
- m_State.WorkState = enWorkStateType.Idle
- m_State.PortState = enCommStateType.Normal
-
- '串口初始化
- SerialPortInit(PortName)
- End Sub
-
-
- #Region "串口"
-
- ''' <summary>
- ''' 初始化串口8位数据位2位停止位,无校验,波特率38400,写缓存4096。设置了串口的事件处理函数。
- ''' </summary>
- ''' <remarks></remarks>
- Private Sub SerialPortInit(ByVal PortName As String)
- SerialPort1.StopBits = IO.Ports.StopBits.One
- SerialPort1.Parity = IO.Ports.Parity.Odd
- SerialPort1.BaudRate = 38400
- SerialPort1.DataBits = 8
- SerialPort1.ReceivedBytesThreshold = 1
- SerialPort1.WriteBufferSize = 4096
-
- AddHandler SerialPort1.DataReceived, AddressOf OnSerialPortReceivedEvent '指定事件触发函数
- AddHandler SerialPort1.ErrorReceived, AddressOf OnSerialErrorReceivedEvent
-
- m_strPortName = PortName
- End Sub
-
- ''' <summary>
- ''' 返回计算机所有串口名称
- ''' </summary>
- ''' <param name="PortNames">[out]返回计算机所有串口名称数组</param>
- ''' <remarks>当需要设置串口时,可能首先调用本函数获取所有的串口名称。</remarks>
- Public Shared Sub GetSerialPortNames(ByRef PortNames As ArrayList)
- PortNames = New ArrayList
- For Each sp As String In My.Computer.Ports.SerialPortNames
- PortNames.Add(sp)
- Next
- End Sub
-
- ''' <summary>
- ''' 关闭串口连接
- ''' </summary>
- ''' <remarks></remarks>
- Public Function ClosePort()
- Dim str As String = ""
- Try
- SerialPort1.Close()
- Catch ex As Exception
- str = ex.ToString
- End Try
- Return str
- End Function
-
复制代码 |