首先将需要读取的PLC内部元件的地址找到,主要内部元件地址如下:
D: PLC-Address*2+1000H;
T: PLC-Address+00C0H;
C: PLC-Address*2+01C0H;
S: PLC-Address*3;
M: PLC-Address*2+0100H;
Y: PLC-Address+00A0H;
X: PLC-Address+0080H;(只能读不能写,输入寄存器必须由外部信号驱动)
PLC-Address元件是指最低位开始后的第N个元件的位置。
一、VC与PLC的串口通讯主要操作:
1、对位元件和字元件状态读操作;
操作对象元件:PLC内部的X、Y、M、S、T、C、D元件
命令通用格式: STX CMD0 ADD LEN EXT CHK
意义: 起始符 读命令 元件起始位 个数 停止符 校验码
数字代码格式: 0X02 0X30 …… …… 0X03 ……
0x30是读操作指令;
ADD是读位元件或字元件的4位起始地址,高位先发,低位后发,以ASCII码的格式发送;
LEN是一次读取位元件或字元件的个数,最多可以读取0xff个字节的元件,也是以ASCII码的形式发送;
CHK是两位和校验,将CMD0,ADD,LEN,EXT三项进行和累计,将和累计的最低两位转化成ASCII,高位先发,低位后发。
在发完上述命令格式代码后,就可以直接读取PLC响应返回的信息,
响应信息格式:STX DATA EXT CHK
意义: 起始符 接收的数据 停止符 校验码
数字代码格式:0x02 …… 0x03 ……
DATA为我们需要读取的数据;
需要注意的是:读取DATA数据时遵循低位先发,高位后发的原则,所以我们解析数据的时候需要注意高低位的转换。
CHK则为DATA,EXT两项的和累计的最后两位转化为ASCII。
2、位元件和字元件状态写操作;
操作对象元件:PLC内部的XYMSTCU元件
命令通用格式:STX CMD1 ADD LEN DATA EXT CHK
意义: 起始符 读命令 元件起始位 个数 写入的数据 停止符 校验码
数字代码格式:0X02 0X31 …… 0X03 ……
0x031是写操作指令;
DATA是待写入PLC缓冲区的数据,低位先发,高位后发,以ASCII码的形式发送;
其他和读指令一样,此处不再重复;
发送后返回值为06,表示写入成功;
返回值为15,表示写入失败;
数据通讯举例:
例1:读D0的值
D0的内部地址为1000H=31H 30H 30H 30H
LEN表示我们需要读字节的个数,0-7为一个字节,D0占两个字节,所以LEN=30H 32H.
计算CHK校验码=CMD0+ADD+LEN+EXT
=30H+31H+30H+31H+30H+30H+32H+03H=157H
所以校验码为35H 37H.
得到完整的数字命令格式为:02H 30H 31H 30H 30H 30H 30H 32H 03H 35H 37H
将这段数字代码发送给PLC,
返回代码:02H 30H 30H 30H 30H 03H 43H 33H
得到数据段DATA为30H,31H,30H,30H=0001B(低位先发,高位后发)=1D
至此得到D0=1.
完成IPC读取PLC内部数据的全部过程。
IO通讯举例:
例2:读取Y1的值
Y1的内部地址是00A0=30H 30H 41H 30H,表示的意思是Y7-Y0的地址,Y1只是其中的一个位。
LEN因为00A0只有一个字节,所以可以去LEN=01D=30H 31H;
计算CHK校验码=36H 35H;
得到完成的数字代码为:02H 30H 30H 30H 41H 30H 30H 31H 03H 36H 35H;
返回代码:02H 30H 32H 03H 36H 35H
数据段为:30H 32H=02D=0010B
从Y7-Y0低往高排列可以知,Y1现在是状态值为1;
如果这里取LEN=2D=30H 32H
发送代码:02H 30H 30H 30H 41H 30H 30H 32H 03H 36H 36H;
返回代码:02H 30H 32H 30H 30H 03H 43H 35H
数据段为:30H 32H 30H 30H=0002B(低位先发,高位后发)=2D
从Y7-Y0低往高排列可以知,Y1现在是状态值为1;
注意:全部过程中,PLC内部程序不需要做任何程序编写。
三、PLC读取IPC数据时:
数据通讯举例:
例1:PLC读取IPC内部参数X的值。
思路:1、先将X的值转化成数字代码形式。
2、再讲X的值发送写入PLC内部数据寄存器中;
3、然后PLC直接读取这个数据寄存器的数据。
设:X=2;数据写入PLC内部数据寄存器D0中
则DATA=X=2=0010H=31H 30H 30H 30H(低位先发,高位后发);
ADD=31H 30H 30H 30H;
LEN=02D=30H 32H.;(D为10进制;H为16进制)
CHK=CMD1+ADD+LEN+DATA+EXT;
=31H+31H+30H+30H+30H+30H+32H+31H+30H+30H+30H+03H=218H
则校验码为:31H 38H
完整的数字代码为:02H 31H 31H 30H 30H 30H 30H 32H 31H 30H 30H 30H 03H 31H 38H
返回值为06表示写入成功,PLC直接读取D0里面的数据即可。
完成PLC读取IPC数据。
当然这只是即时的读取,如果需要可控性的话,需要增加自定义读取和发送标志位,多加个数据用来表示控制字节用。
IO通讯举例:
例2:IPC置位PLC内部位元件Y1
思路:1、确定Y1地址(读操作已说明);
2、就于写入的原理,需要先读取00A0的值;
3、将读取的值与0010进行&运算,确定Y1是否为0;
4、为0,则将读取值与0010进行或运算,再将得到的值转为数字代码形式发送给PLC; 为1,则表示内部Y1已经为1,不需要重复置位;
5、写入成功后返回06;
编写VC程序时需要用到以上思路;
这里我们假设我们只是写入Y1=1来操作:
Y1的PLC内部地址为:00A0H;表示Y7-Y0的地址,Y1只是其中一个位;
LEN取2个字节16位=30H 32H;
写入数据:00A0表示的是Y7-Y0 8个位,需要Y1为1,写入00000010B=02H,但是LEN为2,表示2个字节,所以需要写入0002H转化为30H 32H 30H 30H(低位先发,高位后发);
完整代码:02H 31H 30H 30H 41H 30H 30H 32H 30H 32H 30H 30H 03H 32H 39H
返回:06写入成功。
四、数据通讯VC代码编写分析实例:
例1:将IPC端3个数据:
X=1003.5;Y=-4500;Z=-3.1456
写入PLC中
代码编写步骤:
1、将XYZ分别转化成整数,然后保存其小数位数,这里将XYZ分别都乘以10的N次方,直到其不在 -32767-32767范围后分别保存乘以10的个数在N1,N2,N3中;
从而得到 X=10035 ; N1=1;
Y=-4500; N2=0;
Z=31456; N3=4;
2、将X、Y、Z、N1、N2、N3分别转换成16进制;
3、再转化为16进制ASCII码;
4、将得到的16进制ASCII码按照X、N1、Y、N2、Z、N3的顺序排列进counts[35]数组中;
5、计算校验码;
6、将数据counts[35]每个数转化为对应的两个ASCII码值保存于counts_ascii[70]中;
例如:“35”转化为“3”和“5”;
7、将ASCII码转化为字符串代码保存于a2[70],累加排列输出;
例如:“3”的字符串代码为48+3=51;
8、返回值06,表示写入成功。
例2:读取PLC内部数据X、Y、Z的值
(读取D0-D5的数据)
代码编写步骤:(思路与上例一样)
1、将固定读取的数字代码发送给PLC,
固定读取D0-D5的数字代码为:02H 30H 31H 30H 30H 30H 30H 43H 03H 36H 37H
2、发送成功后,则有数据信息反馈;不成功则返回15;
3、将返回的窗口输出字符串依次保存在字符串数组char s1[84]中;
4、将数组s1转化为数字保存在数据b中;类似:字符串数字51=“3”;
5、将数组b转为16进制ASCII,再转化为10进制保存在数组c中;
例如:“3”“5”=3*10+5=35;再如:35H=5D;
6、将数组c转为2进制,方便判断正负数和后期运算,保存在数值c2中;
7、判断正负数,设立标志位flog;
如果为负数,则将其二进制取反加1后转化为10进制整数;
如果不为负数,则直接转化为10进制整数;
8、得到的数分别保存在D0、D1、D2、D3、D4、D5中(IPC内部变量区别开PLC内部数据寄存器);
自定义运算;
可以得到 X=D0/(10^D1);//D0除以10的D1次方
Y=D2/(10^D3);
Z=D4/(10^D5);
'Private Declare Sub Sleep Lib "kernel32" (ByVal dwseconds As Long) '延时函数毫秒
Dim ik As Integer
Dim str_write() As Byte '发送数组
Dim str_val(0 To 5) As Byte
Dim 非读操作 As Boolean '此位为真是表示有非读命令等待执行,那么暂停读命令,执行非读操作
Dim 何种非读操作 As Integer '此变量用来区分等待的是何种非读命令
Dim 读操作 As Boolean '此变量作用:当有非读命令而读操作的接收处理没有完成时,先完成读命令的接收处理
Dim i As Integer '此变量作用:读操作时因为读的类型不一样,所以每次读一种(如X),然后下一次根据i的数值判断是应该读那种类型。
Dim 第一次 As Boolean
Dim dz As Integer '元件操作地址
Dim lie As Byte, lie1 As Byte, lie2 As Byte '元件操作类型
Dim SRet As Byte
Private Sub Command1_Click(Index As Integer) '写VW0---VW30
Dim shuju As String
Dim shuju1 As String
Dim shuju2 As String
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
非读操作 = True
何种非读操作 = 3
shuju = Right("0000" + Hex(Text4(Index).Text), 4)
shuju1 = ("&H" & Mid(shuju, 1, 2))
shuju2 = ("&H" & Mid(shuju, 3, 2))
ReDim str_write(0 To 38) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H21
str_write(2) = &H21
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H6
str_write(17) = &H5 '写
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2
str_write(23) = &H0
str_write(24) = &H2
str_write(25) = &H0
str_write(26) = &H1
str_write(27) = &H84
str_write(28) = &H0
str_write(29) = &H0
str_write(30) = (Index * 2 * 8) Mod 256
str_write(31) = &H0
str_write(32) = &H4
str_write(33) = &H0
str_write(34) = &H10
str_write(35) = shuju1
str_write(36) = shuju2
str_write(37) = SumChk(str_write)
str_write(38) = &H16
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Command2_Click(Index As Integer) 'S元件状态操作
非读操作 = True
何种非读操作 = 0
dz = Index
lie = &H4
lie1 = &H0
lie2 = &H7C
If Command2(Index).Caption = "S0." + Trim(Index) + "复位" Then
SRet = &H0
Else
SRet = &H1
End If
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Command3_Click(Index As Integer) 'M元件状态操作
非读操作 = True
何种非读操作 = 0
dz = Index
lie = &H83
lie1 = &H0
lie2 = &H7C
If Command3(Index).Caption = "M0." + Trim(Index) + "复位" Then
SRet = &H0
Else
SRet = &H1
End If
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Command4_Click(Index As Integer) 'V元件状态操作
非读操作 = True
何种非读操作 = 0
dz = Index
lie = &H84
lie1 = &H1
lie2 = &H6C
If Command4(Index).Caption = "V0." + Trim(Index) + "复位" Then
SRet = &H0
Else
SRet = &H1
End If
End Sub
Private Sub Command5_Click() '启动
非读操作 = True
何种非读操作 = 1
ReDim str_write(0 To 38) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H21
str_write(2) = &H21
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H7C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &H14
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H28
str_write(18) = &H0
str_write(19) = &H0
str_write(20) = &H0
str_write(21) = &H0
str_write(22) = &H0
str_write(23) = &H0
str_write(24) = &HFD
str_write(25) = &H0
str_write(26) = &H0
str_write(27) = &H9
str_write(28) = &H50
str_write(29) = &H5F
str_write(30) = &H50
str_write(31) = &H52
str_write(32) = &H4F
str_write(33) = &H47
str_write(34) = &H52
str_write(35) = &H41
str_write(36) = &H4D
str_write(37) = SumChk(str_write)
str_write(38) = &H16
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Command6_Click() '停止
ReDim str_write(0 To 34) As Byte '重新定义数组
非读操作 = True
何种非读操作 = 2
str_write(0) = &H68
str_write(1) = &H1D
str_write(2) = &H1D
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H7C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &H10
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H29
str_write(18) = &H0
str_write(19) = &H0
str_write(20) = &H0
str_write(21) = &H0
str_write(22) = &H0
str_write(23) = &H9
str_write(24) = &H50
str_write(25) = &H5F
str_write(26) = &H50
str_write(27) = &H52
str_write(28) = &H4F
str_write(29) = &H47
str_write(30) = &H52
str_write(31) = &H41
str_write(32) = &H4D
str_write(33) = SumChk(str_write)
str_write(34) = &H16
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Combo1_Click() '通讯口选择
Call CommSet '调用通讯口设置过程
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub CommSet()
On Error GoTo err1 '此处作用:如果您选择了电脑中不存在的通讯口,则提示“无效的通讯口”
If MSComm1.PortOpen = True Then MSComm1.PortOpen = False
MSComm1.CommPort = Val(Mid(Combo1.Text, 4, 1))
MSComm1.Settings = "9600,e,8,1"
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
MSComm1.InputLen = 0
MSComm1.RThreshold = 0
MSComm1.InputMode = comInputModeBinary
MSComm1.PortOpen = True
第一次 = False
非读操作 = False
str_val(0) = &H10
str_val(1) = &H2
str_val(2) = &H0
str_val(3) = &H5C
str_val(4) = &H5E
str_val(5) = &H16
Timer1.Enabled = True
Exit Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
err1:
MsgBox Err.Description '错误提示
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Form_Load()
Dim g As Integer
On Error GoTo err1 '此处作用:如果您选择了电脑中不存在的通讯口,则提示“无效的通讯口”
For g = 1 To 9 '添加通讯选择
Combo1.AddItem "Com" & Trim$(Str$(g))
Next g
MSComm1.CommPort = 1
MSComm1.Settings = "9600,e,8,1"
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
MSComm1.InputLen = 0
MSComm1.RThreshold = 0
MSComm1.InputMode = comInputModeBinary
MSComm1.PortOpen = True
第一次 = False
非读操作 = False
str_val(0) = &H10
str_val(1) = &H2
str_val(2) = &H0
str_val(3) = &H5C
str_val(4) = &H5E
str_val(5) = &H16
Timer1.Enabled = True
Exit Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
err1:
MsgBox Err.Description '错误提示
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Form_Unload(Cancel As Integer)
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
If MSComm1.PortOpen = True Then MSComm1.PortOpen = False
End
End Sub
Private Function SumChk(Dats) As Byte '校验和计算
Dim l As Integer, j As Integer
Dim Temp_FCS As Variant
l = UBound(Dats)
For j = 4 To l 'Len 函数,返回 Long,其中包含字符串内字符的数目,或是存储一变量所需的字节数
Temp_FCS = Temp_FCS + str_write(j)
Next j
SumChk = Temp_FCS Mod 256
End Function
Private Function dec2bin(Dats$) As String '转换成二进制
Dim bin8
Dim bin4
Dim bin2
Dim bin1
Dim bin16
Dim bin32
Dim bin64
Dim bin128
If Dats \ 128 >= 1 Then
bin128 = 1
Else
bin128 = 0
End If
If (Dats Mod 128) \ 64 >= 1 Then
bin64 = 1
Else
bin64 = 0
End If
If (Dats Mod 64) \ 32 >= 1 Then 'Mod用来对两个数作除法并且只返回余数
bin32 = 1
Else
bin32 = 0
End If
If (Dats Mod 32) \ 16 >= 1 Then
bin16 = 1
Else
bin16 = 0
End If
If (Dats Mod 16) \ 8 >= 1 Then '\ 运算符用来对两个数作除法并返回一个整数
bin8 = 1
Else
bin8 = 0
End If
If (Dats Mod 8) \ 4 >= 1 Then 'Mod用来对两个数作除法并且只返回余数
bin4 = 1
Else
bin4 = 0
End If
If (Dats Mod 4) \ 2 >= 1 Then
bin2 = 1
Else
bin2 = 0
End If
If Dats Mod 2 = 0 Then
bin1 = 0
Else
bin1 = 1
End If
bin128 = CStr(bin128) 'CStr 函数将一数值转换为 String
bin64 = CStr(bin64)
bin32 = CStr(bin32)
bin16 = CStr(bin16)
bin8 = CStr(bin8) 'CStr 函数将一数值转换为 String
bin4 = CStr(bin4)
bin2 = CStr(bin2)
bin1 = CStr(bin1)
dec2bin = bin128 + bin64 + bin32 + bin16 + bin8 + bin4 + bin2 + bin1
End Function
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub MSComm1_OnComm()
Dim rcv_array() As Byte
Dim rcv_len As Long
Dim read As String, read1 As String
Dim j As Integer
Dim wei(2) As String
If MSComm1.CommEvent = comEvReceive Then 'CommEvent的属性返回的值为comEvReceive时是发生了接收事件.
rcv_array = MSComm1.Input
If 第一次 = True Then '判断发送的是那一组
If Right("00" + Hex(rcv_array(0)), 2) <> "E5" Then '如果返回的不是E5,则重新发数据
Shape6.BackColor = &HC0&
MSComm1.RThreshold = 0
Timer1.Enabled = True
Timer2.Enabled = False
Text5 = "1"
Else '如果是E5,则发最后一组数据
If 非读操作 = True And 读操作 = False Then '如果是非读命令产生的接收事件
Select Case 何种非读操作
Case 0 '置/复位
MSComm1.RThreshold = 24
Case 1 'PLC启动
MSComm1.RThreshold = 20
Case 2 'PLC停止
MSComm1.RThreshold = 20
Case 3 '数值写入
MSComm1.RThreshold = 18
End Select
Else '如果是实时监控
Select Case i
Case 0 '读M0.0—M0.7
MSComm1.RThreshold = 28
Case 1 '读T0
MSComm1.RThreshold = 30
Case 2 '读V0.0—V0.7
MSComm1.RThreshold = 28
Case 3 '读输入
MSComm1.RThreshold = 29
Case 4 '读VW0—VW15
MSComm1.RThreshold = 59
Case 5 '读输出
MSComm1.RThreshold = 29
Case 6 '读S0.0—S0.7
MSComm1.RThreshold = 28
Case 7 '读C0
MSComm1.RThreshold = 30
End Select
End If '判断非读操作结束
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
MSComm1.Output = str_val '发送命令
第一次 = False
Text5 = "2"
End If '判断返回的E5是否正确结束
Else '如果是第二组命令
rcv_len = UBound(rcv_array) '返回一个 Long 型数据,其值为指定的数维组可用的最大下标
For j = 0 To rcv_len
read = read & Right("00" + Hex(rcv_array(j)), 2)
Next j
If 非读操作 = True And 读操作 = False Then '如果是非读命令产生的接收事件
非读操作 = False '
Shape6.BackColor = &HC0&
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
Timer1.Enabled = True
Else '如果是实时监控命令产生的接收事件
Select Case i
Case 0 '读M0.0—M0.7
read1 = Val("&H" + Mid(Right(read, 6), 1, 2))
wei(0) = dec2bin(read1) '调用十二进转二进制过程
For j = 0 To 7
If Mid(wei(0), 8 - j, 1) = "1" Then
Shape4(j).BackColor = &HC0&
Command3(j).Caption = "M0." + Trim(j) + "复位"
Else
Shape4(j).BackColor = &HE0E0E0
Command3(j).Caption = "M0." + Trim(j) + "置位"
End If
Next j
Case 1 '读T0
read1 = Val("&H" + Mid(Right(read, 8), 1, 4))
Text2.Text = read1 'T当前值显示
Case 2 '读V0.0—V0.7
read1 = Val("&H" + Mid(Right(read, 6), 1, 2))
wei(0) = dec2bin(read1) '调用十二进转二进制过程
For j = 0 To 7
If Mid(wei(0), 8 - j, 1) = "1" Then
Shape5(j).BackColor = &HC0&
Command4(j).Caption = "V0." + Trim(j) + "复位"
Else
Shape5(j).BackColor = &HE0E0E0
Command4(j).Caption = "V0." + Trim(j) + "置位"
End If
Next j
Case 3 '读输入
read1 = Mid(Right(read, 8), 1, 4)
wei(0) = dec2bin(Val("&H" + Mid(read1, 1, 2))) '调用十二进转二进制过程
wei(1) = dec2bin(Val("&H" + Right(read1, 2))) '调用十二进转二进制过程
wei(2) = wei(1) + wei(0)
For j = 0 To 15
If Mid(wei(2), 16 - j, 1) = "1" Then
Shape1(j).BackColor = &HC0&
Else
Shape1(j).BackColor = &HE0E0E0
End If
Next j
Case 4 '读VW0—VW15
read1 = Mid(Right(read, 68), 1, 64)
For j = 0 To 15
Text1(j).Text = Val("&H" + Mid(read1, 1 + j * 4, 4))
Next j
Case 5 '读输出
read1 = Mid(Right(read, 8), 1, 4)
wei(0) = dec2bin(Val("&H" + Mid(read1, 1, 2))) '调用十二进转二进制过程
wei(1) = dec2bin(Val("&H" + Right(read1, 2))) '调用十二进转二进制过程
wei(2) = wei(1) + wei(0)
For j = 0 To 15
If Mid(wei(2), 16 - j, 1) = "1" Then
Shape2(j).BackColor = &HC0&
Else
Shape2(j).BackColor = &HE0E0E0
End If
Next j
Case 6 '读S0.0—S0.7
read1 = Val("&H" + Mid(Right(read, 6), 1, 2))
wei(0) = dec2bin(read1) '调用十二进转二进制过程
For j = 0 To 7
If Mid(wei(0), 8 - j, 1) = "1" Then
Shape3(j).BackColor = &HC0&
Command2(j).Caption = "S0." + Trim(j) + "复位"
Else
Shape3(j).BackColor = &HE0E0E0
Command2(j).Caption = "S0." + Trim(j) + "置位"
End If
Next j
Case 7 '读C0
read1 = Val("&H" + Mid(Right(read, 8), 1, 4))
Text3.Text = read1 'C当前值显示
i = -1 '常规读取全部完成,从头开始,因为下面有一个+1命令,所以此处赋-1
End Select
i = i + 1 '进行下一个类型的常规读取
读操作 = False '读操作接收处理完成
Shape6.BackColor = &HC0&
Timer1.Enabled = True '进行下一个类型的常规读取
Timer2.Enabled = False
End If
End If '判断第一组发送命令结束
End If
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Timer1_Timer()
第一次 = True
MSComm1.RThreshold = 1 '因为PLC接收到写或是置位命令,只返回一个字符,所以设为1(RThreshold:定义接收缓冲区接收多少个字符后产生COMMFX_OnComm事件)
If 非读操作 = True Then '如果有非读命令存在
Select Case 何种非读操作
Case 0
ReDim str_write(0 To 37) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H20
str_write(2) = &H20
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = lie2 '类型
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H5
str_write(17) = &H5
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H1
str_write(23) = &H0
str_write(24) = &H1
str_write(25) = &H0
str_write(26) = lie1 '存储器类型,01:V存储器 00:其它
str_write(27) = lie '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0
str_write(30) = dz
str_write(31) = &H0
str_write(32) = &H3
str_write(33) = &H0
str_write(34) = &H1
str_write(35) = SRet '置/复位
str_write(36) = SumChk(str_write)
str_write(37) = &H16
End Select
Else ' 如果没有非读命令则执行常规轮询
读操作 = True '置真的目的:当有非读命令而读操作的接收处理没有完成时,先完成读命令的接收处理
Select Case i
Case 0 '读M0.0—M0.7
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2 '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H1 '以字节为单位,连续读取的字节数
str_write(25) = &H0
str_write(26) = &H0 '存储器类型,01:V存储器 00:其它
str_write(27) = &H83 '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 1 '读T0
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H7C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H8 '&H8
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H1F '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H1 '读取数据个数
str_write(25) = &H0
str_write(26) = &H0 '存储器类型,01:V存储器 00:其它
str_write(27) = &H1F '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 2 '读V0.0—V0.7
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2 '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H1 '读取数据个数
str_write(25) = &H0
str_write(26) = &H1 '存储器类型,01:V存储器 00:其它
str_write(27) = &H84 '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 3 '读输入
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2 '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H2 '读取数据个数
str_write(25) = &H0
str_write(26) = &H0 '存储器类型,01:V存储器 00:其它
str_write(27) = &H81 '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 4 '读VW0—VW15
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2 '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H20 '以字节为单位,连续读取的字节数
str_write(25) = &H0
str_write(26) = &H1 '存储器类型,01:V存储器 00:其它
str_write(27) = &H84 '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 5 '读输出
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2 '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H2 '读取数据个数
str_write(25) = &H0
str_write(26) = &H0 '存储器类型,01:V存储器 00:其它
str_write(27) = &H82 '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 6 '读S0.0—S0.7
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H6C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H0
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H2 '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H1 '读取数据个数
str_write(25) = &H0
str_write(26) = &H0 '存储器类型,01:V存储器 00:其它
str_write(27) = &H4 '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
Case 7 '读C0
ReDim str_write(0 To 32) As Byte '重新定义数组
str_write(0) = &H68
str_write(1) = &H1B
str_write(2) = &H1B
str_write(3) = &H68
str_write(4) = &H2
str_write(5) = &H0
str_write(6) = &H7C
str_write(7) = &H32
str_write(8) = &H1
str_write(9) = &H0
str_write(10) = &H0
str_write(11) = &H0
str_write(12) = &H12 '&H8
str_write(13) = &H0
str_write(14) = &HE
str_write(15) = &H0
str_write(16) = &H0
str_write(17) = &H4 '读
str_write(18) = &H1
str_write(19) = &H12
str_write(20) = &HA
str_write(21) = &H10
str_write(22) = &H1E '读取位,字节,字,双字(1,2,4,8)
str_write(23) = &H0
str_write(24) = &H1 '读取数据个数
str_write(25) = &H0
str_write(26) = &H0 '存储器类型,01:V存储器 00:其它
str_write(27) = &H1E '读不同元件的代码
str_write(28) = &H0
str_write(29) = &H0 '高位地址 地址转换地16进制 (字节号*8+位号)\256
str_write(30) = &H0 '低位地址 地址转换地16进制 (字节号*8+位号)Mod 256
str_write(31) = SumChk(str_write)
str_write(32) = &H16
End Select
End If
MSComm1.InBufferCount = 0
MSComm1.OutBufferCount = 0
MSComm1.Output = str_write '发送命令
ik = 0
Timer1.Enabled = False '等待接收处理结束后再进行下一次的命令发送
Timer2.Enabled = True
Text5 = "0"
Shape6.BackColor = &HE0E0E0
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Private Sub Timer2_Timer()
ik = ik + 1
If ik > 3 And Timer1.Enabled = False Then
Timer1.Enabled = True
End If
End Sub
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------