附件:问题描述.doc
[本地下载]谁能帮我,感激涕零啊!
附件里有详细的描述,有梯形图的截图,非常直观。
我用VB写的程序与施耐德PLC(PLC型号:BMX P34 2020)实现以太网通信。调用winsock控件,采用modbus协议。
已经顺利实现读线圈、写线圈、读寄存器整数、读寄存器浮点数。(唯独没有实现写寄存器功能,原因在下)
因为有个很奇怪的问题,在所有的读写过程中,不管是地址还是数据内容,每个字节都不可以超过&H80(十六进制数80)。
比如:向字寄存器%MW42 写数据,该寄存器存的是整数,数据长度为一个字(也就是16位二进制,4位16进制字符):
一、向寄存器%MW42(其地址为十六进制数002A)写入字符&H000F,运行结果如下:
%MW42数据类型整数
1、VB里的发送数据程序:
(1) Private Sub Command1_Click()
(2) Dim str2(12) As Byte
(3) str2(0) = &H0 '交换识别号高字节,通常为 0
(4) str2(1) = &H0 '交换识别号低字节,通常为 0
(5) str2(2) = &H0 '协议识别号高字节,为 0
(6) str2(3) = &H0 '协议识别号低字节,为 0
(7) str2(4) = &H0 '字节长度高字节
(8) str2(5) = &H6 '字节长度低字节
(9) str2(6) = &HFF '单元识别号,确省为 255
(10) str2(7) = &H6 'modbus功能码,06为预置单寄存器
(11) str2(8) = &H0 '寄存器的起始地址高字节
(12) str2(9) = &H2A '寄存器的起始地址低字节
(13) str2(10) = &H0 '数据内容高字节
(14) str2(11) = &HF '数据内容低字节
(15) Dim bStrQ As String
(16) Dim Q As Integer
(17) For Q = 0 To 11
(18) bStrQ = bStrQ & Chr(str2(Q))
(19) Next
(20) Winsock1.SendData bStrQ
(21) Exit Sub
(22) End Sub
运行之后,一切正常。可以在编程软件里看到寄存器里数据为15。
二、向寄存器%MW42写入字符&H0080(也就是十进制数128),运行结果如下:
运行前
1、VB里的发送数据程序:
Private Sub Command1_Click()
Dim str2(12) As Byte
str2(0) = &H0 '交换识别号高字节,通常为 0
str2(1) = &H0 '交换识别号低字节,通常为 0
str2(2) = &H0 '协议识别号高字节,为 0
str2(3) = &H0 '协议识别号低字节,为 0
str2(4) = &H0 '字节长度高字节
str2(5) = &H6 '字节长度低字节
str2(6) = &HFF '单元识别号,确省为 255
str2(7) = &H6 'modbus功能码,06为预置单寄存器
str2(8) = &H0 '寄存器的起始地址高字节
str2(9) = &H2A '寄存器的起始地址低字节
str2(10) = &H0 '数据内容高字节
str2(11) = &H80 '数据内容低字节
Dim bStrQ As String
Dim Q As Integer
For Q = 0 To 11
bStrQ = bStrQ & Chr(str2(Q))
Next
Winsock1.SendData bStrQ
Exit Sub
End Sub
2、运行之后,依然正常 寄存器%MW42 里的数据是128。
注意:接下来是问题的开始!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
三、向寄存器%MW42写入字符&H0081,也就是十进制129运行结果如下:
运行前
1、VB里的发送数据程序:
Private Sub Command1_Click()
Dim str2(12) As Byte
str2(0) = &H0 '交换识别号高字节,通常为 0
str2(1) = &H0 '交换识别号低字节,通常为 0
str2(2) = &H0 '协议识别号高字节,为 0
str2(3) = &H0 '协议识别号低字节,为 0
str2(4) = &H0 '字节长度高字节
str2(5) = &H6 '字节长度低字节
str2(6) = &HFF '单元识别号,确省为 255
str2(7) = &H6 'modbus功能码,06为预置单寄存器
str2(8) = &H0 '寄存器的起始地址高字节
str2(9) = &H2A '寄存器的起始地址低字节
str2(10) = &H0 '数据内容高字节
str2(11) = &H81 '数据内容低字节
Dim bStrQ As String
Dim Q As Integer
For Q = 0 To 11
bStrQ = bStrQ & Chr(str2(Q))
Next
Winsock1.SendData bStrQ
Exit Sub
End Sub
2、运行之后
彻底晕了:%MW42里的数据内容不是&H0081,竟然变成了&H0000!!!!!!!!!!
接下来凡是写的数据内容不管是高字节,还是低字节,只要超过&H80,全都会变成00!!!!!!!!!!
比如:发送&H00A1,实际发出去的是&H 0000;
发送&H81A1,实际发出去的还是&H 0000;
四、那我就想,如果PLC的寄存器%MW42里存的是&H0081,也就是129,看看能读出什么来
1、 读寄存器%MW42的内容
首先用传送指令 吧数据129赋值给寄存器%MW42
VB程序如下:
Private Sub Command1_Click()
Dim str2(12) As Byte
str2(0) = &H0 '交换识别号高字节,通常为 0
str2(1) = &H0 '交换识别号低字节,通常为 0
str2(2) = &H0 '协议识别号高字节,为 0
str2(3) = &H0 '协议识别号低字节,为 0
str2(4) = &H0 '字节长度高字节
str2(5) = &H6 '字节长度低字节
str2(6) = &HFF '单元识别号,确省为 255
str2(7) = &H3 'modbus功能码,03读寄存器
str2(8) = &H0 '寄存器的起始地址高字节
str2(9) = &H2A '寄存器的起始地址低字节
str2(10) = &H0 '数据长度高字节
str2(11) = &H1 '数据长度低字节
Dim bStrQ As String
Dim Q As Integer
For Q = 0 To 11
bStrQ = bStrQ & Chr(str2(Q))
Next
Winsock1.SendData bStrQ
Exit Sub
End Sub
然后,运行PLC
运行VB读寄存器
读寄存器%MW42里的内容129,返回结果就是&H0081。。。。。正常!!!!!!!!!!!!!!!!!!!!
可是………..写&H0081(十进制129)给字寄存器%MW42就是&H0000
五、更改%MW42的数据类型,由INT改为BYTE(单字节整形)
运行结果依旧是同上,凡是写的数据内容不管是高字节,还是低字节,只要超过&H80,全都会变成00!!!!!!!!!!
六、不仅如此,假设我写一个线圈,如果线圈的地址是十进制129,也就是16进制81,他的操作对象实际是线圈00。
1、置位线圈%M129(十六进制地址为0081),VB程序如下
Private Sub Command1_Click()
Dim str2(12) As Byte
str2(0) = &H0 '交换识别号高字节,通常为 0
str2(1) = &H0 '交换识别号低字节,通常为 0
str2(2) = &H0 '协议识别号高字节,为 0
str2(3) = &H0 '协议识别号低字节,为 0
str2(4) = &H0 '字节长度高字节
str2(5) = &H6 '字节长度低字节
str2(6) = &HFF '单元识别号,确省为 255
str2(7) = &H5 'modbus功能码,05为强制线圈
str2(8) = &H0 '线圈的起始地址高字节
str2(9) = &H81 '线圈的起始地址低字节
str2(10) = &HFF '强制线圈为1
str2(11) = &H0
Dim bStrQ As String
Dim Q As Integer
For Q = 0 To 11
bStrQ = bStrQ & Chr(str2(Q))
Next
Winsock1.SendData bStrQ
Exit Sub
End Sub
运行结果地址为129(十六进制0081)的线圈没有任何变化。
但是地址为0的线圈,竟然置1了。。
看也就是说,地址是&H0081竟然变成了地址&H0000。
到底是什么原因,我也很纠结,不道是VB的程序不对,还是PLC有问题,我对MODBUS协议也不是十分的了解。
这也导致我一直没有写寄存器成功。
bStrQ = bStrQ & Chr(str2(Q))
Next
Winsock1.SendData bStrQ
这个地方有问题??
我很无奈,我需要帮助。。。。。。
附:VB通讯程序如下:
VB通讯程序如下:
Private Sub Command1_Click()
Dim str2(12) As Byte
str2(0) = &H0 '交换识别号高字节,通常为 0
str2(1) = &H0 '交换识别号低字节,通常为 0
str2(2) = &H0 '协议识别号高字节,为 0
str2(3) = &H0 '协议识别号低字节,为 0
str2(4) = &H0 '字节长度高字节
str2(5) = &H6 '字节长度低字节
str2(6) = &HFF '单元识别号,确省为 255
str2(7) = &H6 'modbus功能码,06为预置单寄存器
str2(8) = &H0 '寄存器的起始地址高字节
str2(9) = &H2A '寄存器的起始地址低字节
str2(10) = &H0 '数据内容高字节
str2(11) = &HF '数据内容低字节
Dim bStrQ As String
Dim Q As Integer
For Q = 0 To 11
bStrQ = bStrQ & Chr(str2(Q))
Next
Winsock1.SendData bStrQ
Exit Sub
End Sub
Private Sub Form_Load() ‘与施耐德PLC仿真器建立通信连接
Winsock1.Close
Winsock1.Connect "192.168.1.110", 502 ’PLC的IP地址与通讯端口号
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)’将PLC返回的数据显示在text1
Dim strdata() As Byte
Dim m, n As Integer
Dim t As String
m = Winsock1.BytesReceived
ReDim strdata(m)
Winsock1.GetData strdata, vbByte, m
For n = 0 To m - 1
t = t & Hex(strdata(n))
Next
Text1.Text = t
End Sub