登录
首页 PLC论坛 施耐德电气PLC
回帖 发帖
正文

主题:一个PLC奇怪而令我百思不得其解的事。(VB、施耐德PLC、MODBUS、以太网)

点击:2348 回复:7

附件:问题描述.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
10-05-28 20:04
各位高手大哥大姐们,怎么零回复啊。。。我没这么丑吧。。。老板还在催我交活呢。。。好心的人士帮我下吧
10-05-29 16:59
我是真想帮你啊,可惜啊,我不懂哦!努力吧
10-05-29 22:59
呵呵,这位兄弟,我来回复你吧.
你的问题出在    bStrQ = bStrQ & Chr(str2(Q))语句. chr不认129等几个值(认&Hff=255).
10-05-30 00:03
啊!!谢谢3楼这位大师的不吝赐教,感谢之情溢于言表,也感谢工控网这个平台,这个问题困扰我5天了算是找到头绪了。。。。
   我刚毕业不到两年,赤裸裸的不足逼迫我去努力!努力!!在努力!!!
   额,这个是我自己为自己加油哈,请各位无视。。。
10-05-30 19:14
再努力!!!
应该感谢你自己,把问题描述清楚了,而且贴了大量的信息.蛮勤奋,有头脑.
你如果只是贴个附件,留个qq或者email.大家就没办法帮到你了.
10-05-31 10:18
这个问题,现在我已圆满解决,现把解决方案说一下,希望有类似困难的朋友能少走弯路。因为我发现这个可以用1分钟解决的问题  我用了5天!!!!
   问题就出在  bStrQ = bStrQ & Chr(str2(Q))
                         Winsock1.SendData bStrQ
这就牵扯到winsock1.senddata的用法了,格式是:winsock1.senddata   字符串或是字节数组
程序改成如下就没问题了:
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  '数据内容低字节
       Winsock1.SendData str2()
End Sub
...............................................就这么简单,我忙活了5天!!!!!!
10-05-31 18:00
哦,我也遇到一模一样的问题了,终于参照楼主的方法从发送字符串改成发送数据就解决了,多谢指导
12-05-28 14:50

工控新闻

更多新闻资讯