三菱PLC 内部寄存器 通信 地址计算 算法

    首先将需要读取的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
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章