[吐血奉献]VB与三菱FX系列PLC通信模块
'需要使用一个MSComm控件
'函数作者:纪小年 https://8jxn.com
'BR, BW, BT, WR, WW, WT指令由5个字符构成
'定时器计数器为2+"0"+2
Public WordReadKey As String
Public WordReadKey1 As Single
Public WordReadKey2 As Single
Public BitReadKey As String
'以下为PLC通讯控制代码.是控制协议的一部分
Public Const STX = ""
Public Const ENQ = ""
Public Const ACK = ""
Public Const ETX = ""
Declare Function timeGetTime Lib "winmm.dll" () As Long
Public Sub Delay_ms(ByVal My_Time As Integer)
Dim SaveTime As Double
SaveTime = timeGetTime
While Not My_Unload And timeGetTime < SaveTime + My_Time
DoEvents
Wend
End Sub
Public Function PC_Test(MyRsCom As MSComm, MyRsComPort As Integer) As String
If MyRsCom.PortOpen = True Then MyRsCom.PortOpen = False
MyRsCom.CommPort = MyRsComPort
MyRsCom.Settings = "9600,N,7,1"
MyRsCom.PortOpen = True
Again: SD = ENQ + "00FFPC3"
MyRsCom.Output = SD
Delay_ms (100)
If My_Unload Then Exit Function
RD = MyRsCom.Input
i = i + 1
If Left(RD, 5) <> STX + "00FF" And i < 20 Then GoTo Again
MyRsCom.PortOpen = False
If i = 20 Then
PC_Test = ""
Else
PC_Test = Mid(RD, 6, 2)
Select Case PC_Test
Case "F2": PC_Test = "FX1s"
Case "8E": PC_Test = "FX0n"
Case "8D": PC_Test = "FX2 or FX2c"
Case "9E": PC_Test = "FX1n or FX1nc"
Case "9D": PC_Test = "FX2n or FX2nc"
Case "F3": PC_Test = "FX3u or FX3uc"
Case Else: PC_Test = "Other"
End Select
End If
End Function
'******************************************************************
'函数名 : PC_WordWrite
'输入值 : MyRsCom,MyRsComPort,Adress,Number,Word
'输入说明: MyRsCom MSComm 是传送的控件
' MyRsComPort Integer 是传送数据的串口号
' Adress String 就是要写入的起始地址,5个字符,示例:M0640,D0001。可写入XYMSTNCNDR,其中XY为8进制数,其余为10进制数
' Nuber Integer WW指令以字为单位,所以Nuber值就是字的个数。但如果写入的是CN200-CN255,则Nuber值就是双字的个数。
' Word String 就是要写入的内容,每个字4个字符,以十六进制表示,示例:2347。
'返回值 : PC_WordWrite
'返回说明: 返回1,地址错误
' 返回2,传入数量超范围
' 返回3,传入数据错误
' 返回4,传送次数过多
'******************************************************************
Public Function PC_WordWrite(MyRsCom As MSComm, MyRsComPort As Integer, Adress As String, Number As Integer, ByVal Word As String) As Integer
If Len(Adress) <> 5 Or (Mid(Adress, 1, 1) <> "X" And Mid(Adress, 1, 1) <> "Y" _
And Mid(Adress, 1, 1) <> "M" And Mid(Adress, 1, 1) <> "S" _
And Mid(Adress, 1, 1) <> "D" And Mid(Adress, 1, 1) <> "R" _
And Mid(Adress, 1, 2) <> "TS" And Mid(Adress, 1, 2) <> "CS") Then
PC_WordWrite = 1
Exit Function
End If
If Number < 1 Or Number > 64 Or (Mid(Adress, 1, 2) = "CN" And Number > 32) Then
PC_WordWrite = 2
Exit Function
End If
If Len(Word) <> Number * 4 Then
PC_WordWrite = 3
Exit Function
End If
Dim MyNum As String
MyNum = CStr(Hex(Number))
For i = 1 To 2 - Len(MyNum)
MyNum = "0" & MyNum
Next i
If MyRsCom.PortOpen = True Then MyRsCom.PortOpen = False
MyRsCom.CommPort = MyRsComPort
MyRsCom.Settings = "9600,N,7,1"
MyRsCom.PortOpen = True
i = 1
RD = ""
SD = ENQ + "00FFWW3" + Adress + MyNum + Word
MyRsCom.Output = SD
Again: Delay_ms (100)
If My_Unload Then Exit Function
RD = RD + MyRsCom.Input
i = i + 1
Debug.Print RD
If Left(RD, 5) <> ACK + "00FF" And i < 20 Then GoTo Again
MyRsCom.PortOpen = False
If i = 20 Then
PC_WordWrite = 4
Exit Function
End If
PC_WordWrite = 0
End Function
'******************************************************************
'函数名 : PC_WordRead
'输入值 : MyRsCom,MyRsComPort,Adress,Number
'输入说明: MyRsCom MSComm 是传送的控件
' MyRsComPort Integer 是传送数据的串口号
' Adress String 就是要写入的起始地址,5个字符,示例:M0640,D0001。可写入XYMSTNCNDR,其中XY为8进制数,其余为10进制数
' Nuber Integer WW指令以字为单位,所以Nuber值就是字的个数。但如果写入的是CN200-CN255,则Nuber值就是双字的个数。
'返回值 : PC_WordWrite
'返回说明: 返回1,地址错误
' 返回2,传入数量超范围
' 返回3,传送次数过多
'******************************************************************
Public Function PC_WordRead(MyRsCom As MSComm, MyRsComPort As Integer, Adress As String, Number As Integer) As Integer
On Error GoTo ll
If Len(Adress) <> 5 Or (Mid(Adress, 1, 1) <> "X" And Mid(Adress, 1, 1) <> "Y" _
And Mid(Adress, 1, 1) <> "M" And Mid(Adress, 1, 1) <> "S" _
And Mid(Adress, 1, 1) <> "D" And Mid(Adress, 1, 1) <> "R" _
And Mid(Adress, 1, 2) <> "TS" And Mid(Adress, 1, 2) <> "CS") Then
PC_WordRead = 1
Exit Function
End If
If Number < 1 Or Number > 64 Or (Mid(Adress, 1, 2) = "CN" And Number > 32) Then
PC_WordRead = 2
Exit Function
End If
Dim MyNum As String
MyNum = CStr(Hex(Number))
For i = 1 To 2 - Len(MyNum)
MyNum = "0" & MyNum
Next i
If MyRsCom.PortOpen = True Then MyRsCom.PortOpen = False
MyRsCom.CommPort = MyRsComPort
MyRsCom.Settings = "9600,N,7,1"
MyRsCom.PortOpen = True
i = 1
Again: SD = ENQ + "00FFWR3" + Adress + MyNum
MyRsCom.Output = SD
j = 1
RD = ""
Again1: Delay_ms (50)
If My_Unload Then Exit Function
RD = RD + MyRsCom.Input
i = i + 1
j = j + 1
If Len(RD) <> Number * 4 + 6 And j < 10 Then GoTo Again1
If Left(RD, 5) <> STX + "00FF" And i < 5 Then GoTo Again
MyRsCom.PortOpen = False
If i = 20 Then
PC_WordRead = 3
Exit Function
End If
WordReadKey = Mid(RD, 6, Number * 4)
PC_WordRead = 0
If Number = 1 Then
WordReadKey1 = CDec("&H" + WordReadKey)
Else: WordReadKey1 = 0
End If
If Number = 2 Then
WordReadKey2 = CDec("&H" + Mid(WordReadKey, 5, 4) + Mid(WordReadKey, 1, 4))
Else: WordReadKey2 = 0
End If
Exit Function
ll:
MsgBox "错误代码 " & Err.Number & Chr(13) & Err.Description, vbQuestion + vbOKOnly, "提示"
End Function
'******************************************************************
'函数名 : PC_BitWrite
'输入值 : MyRsCom,MyRsComPort,Adress,Number,Word
'输入说明: MyRsCom MSComm 是传送的控件
' MyRsComPort Integer 是传送数据的串口号
' Adress String 就是要写入的起始地址,5个字符,示例:M0640。可写入XYMSTSCS
' Nuber Integer BW指令以位为单位,所以Nuber值就是位的个数。但如果写入的是CN200-CN255,则Nuber值就是双字的个数。
' Word String 就是要写入的内容,每个位1个字符,以二进制表示,示例:0,1。
'返回值 : PC_BitWrite
'返回说明: 返回1,地址错误
' 返回2,传入数量超范围
' 返回3,传入数据错误
' 返回4,传送次数过多
'******************************************************************
Public Function PC_BitWrite(MyRsCom As MSComm, MyRsComPort As Integer, Adress As String, Number As Integer, Word As String) As Integer
If Len(Adress) <> 5 Or (Mid(Adress, 1, 1) <> "X" And Mid(Adress, 1, 1) <> "Y" _
And Mid(Adress, 1, 1) <> "M" And Mid(Adress, 1, 1) <> "S" _
And Mid(Adress, 1, 2) <> "TS" And Mid(Adress, 1, 2) <> "CS") Then
PC_BitWrite = 1
Exit Function
End If
If Number < 1 Or Number > 160 Then
PC_BitWrite = 2
Exit Function
End If
If Len(Word) <> Number Then
PC_BitWrite = 3
Exit Function
End If
Dim MyNum As String
MyNum = CStr(Hex(Number))
For i = 1 To 2 - Len(MyNum)
MyNum = "0" & MyNum
Next i
If MyRsCom.PortOpen = True Then MyRsCom.PortOpen = False
MyRsCom.CommPort = MyRsComPort
MyRsCom.Settings = "9600,N,7,1"
MyRsCom.PortOpen = True
i = 1
SD = ENQ + "00FFBW3" + Adress + MyNum + Word
MyRsCom.Output = SD
Again: Delay_ms (50)
If My_Unload Then Exit Function
RD = MyRsCom.Input
i = i + 1
If Left(RD, 5) <> ACK + "00FF" And i < 20 Then GoTo Again
MyRsCom.PortOpen = False
If i = 20 Then
PC_BitWrite = 4
Exit Function
End If
PC_BitWrite = 0
End Function
'******************************************************************
'函数名 : PC_BitRead
'输入值 : MyRsCom,MyRsComPort,Adress,Number
'输入说明: MyRsCom MSComm 是传送的控件
' MyRsComPort Integer 是传送数据的串口号
' Adress String 就是要读出的起始地址,5个字符,示例:M0640。可读出XYMSTSCS
' Nuber Integer BW指令以位为单位,所以Nuber值就是位的个数。但如果读出的是CN200-CN255,则Nuber值就是双字的个数。
'返回值 : PC_BitRead
'返回说明: 返回1,地址错误
' 返回2,传入数量超范围
' 返回3,传送次数过多
'******************************************************************
Public Function PC_BitRead(MyRsCom As MSComm, MyRsComPort As Integer, Adress As String, Number As Integer) As Integer
If Len(Adress) <> 5 Or (Mid(Adress, 1, 1) <> "X" And Mid(Adress, 1, 1) <> "Y" _
And Mid(Adress, 1, 1) <> "M" And Mid(Adress, 1, 1) <> "S" _
And Mid(Adress, 1, 2) <> "TS" And Mid(Adress, 1, 2) <> "CS") Then
PC_BitRead = 1
Exit Function
End If
If Number < 1 Or Number > 256 Then
PC_BitRead = 2
Exit Function
End If
Dim MyNum As String
MyNum = CStr(Hex(Number))
For i = 1 To 2 - Len(MyNum)
MyNum = "0" & MyNum
Next i
If Number = 256 Then MyNum = "00"
If MyRsCom.PortOpen = True Then MyRsCom.PortOpen = False
MyRsCom.CommPort = MyRsComPort
MyRsCom.Settings = "9600,N,7,1"
MyRsCom.PortOpen = True
i = 1
Again: SD = ENQ + "00FFBR3" + Adress + MyNum
MyRsCom.Output = SD
j = 1
RD = ""
Again1: Delay_ms (50)
If My_Unload Then Exit Function
RD = RD + MyRsCom.Input
i = i + 1
j = j + 1
If Len(RD) <> Number + 6 And j < 10 Then GoTo Again1
If Left(RD, 5) <> STX + "00FF" And i < 5 Then GoTo Again
MyRsCom.PortOpen = False
If i = 20 Then
PC_BitRead = 3
Exit Function
End If
BitReadKey = Mid(RD, 6, Number)
PC_BitRead = 0
End Function