我用MSCOMM控件和PLC通讯,用PLC的通讯协议,发一条命令它回一条,但必须得等PLC回复后才能发第二条命令。我用timer控件循环地发命令,处理收到的数据。但这样一个timer周期大概要2、3秒,谈不上实时地更新显示数据。以前用触摸屏配套的组态软件编程,如果是显示PLC某个地址的状态,PLC有变化马上能显示出来,一页屏上可以监视显示许多个地址,不知道他们是怎么做到的?

解决方案 »

  1.   

    首先我印象中,timer是可以设置发出命令的时间的啊
      

  2.   

    请大家看仔细 lz已经首先否定了用循环的方法了
    用timer已经可以到毫秒了 lz还是嫌太慢 
    如果用循环 中间不用doevents系统会假死 用了doevents循环会更慢
      

  3.   

    我是在timer里调用过程发命令,然后doevents等待接受事件,接受完了再处理数据并显示,然后发第二个命令
    对于循环我也有fzx4936的顾虑。我奇怪人家触摸屏的组态软件是怎么做的?
      

  4.   

    LZ:完全可由Timer控件实现轮询PLC,而下位机返回数据的接收由MSCOMM控件的ONCOMM事件实现.其关键取决于你的PC与PLC间的通信协议.
      

  5.   

    LS:我就是用timer轮询,然后等待控件的接受事件。
    LSS:难道是波特率的关系?我只设到9600,而以前用的触摸屏是115200。
    有没有人知道组态软件内部都是怎么做的?
      

  6.   

    LZ:请将你的PC与PLC间的通信协议叙述一下? 
     
     
      

  7.   

    可能的原因:1. 人家组态软件发一条命令,返回的是一批数据,要看你如何使用PLC协议,如果一个地址一个地址地读,当然慢了。2. 电脑到PLC的硬件连接,直接连就最好了,如果用非工业无线模块、USB转(新电脑都没有配置串口)什么的,
       
        可能会产生莫名其妙的副作用。建议:1. 预先在命令数组填充全部命令,用一个timer每次发一个命令(发送周期取决于PLC协议),
       
       在oncomm事件处接收数据,然后放入“命令-数据”数组。   如果在“命令-数据”数组里加入时间标记,还可以判断响应是否符合要求。2. 用另外一个timer专门处理前面的“命令-数据”数组,如果处理快的话,就等待前面的数据,
      
       可以设置两个变量来协调两个timer。这样就可以做到类似异步多线程的效果,感觉流畅,而且不用doevents。
      

  8.   

    可能的原因:1. 人家组态软件发一条命令,返回的是一批数据,要看你如何使用PLC协议,如果一个地址一个地址地读,当然慢了。2. 电脑到PLC的硬件连接,直接连就最好了,如果用非工业无线模块、USB转(新电脑都没有配置串口)什么的,
       
        可能会产生莫名其妙的副作用。建议:1. 预先在命令数组填充全部命令,用一个timer每次发一个命令(发送周期取决于PLC协议),
       
       在oncomm事件处接收数据,然后放入“命令-数据”数组。   如果在“命令-数据”数组里加入时间标记,还可以判断响应是否符合要求。2. 用另外一个timer专门处理前面的“命令-数据”数组,如果处理快的话,就等待前面的数据,
      
       可以设置两个变量来协调两个timer。这样就可以做到类似异步多线程的效果,感觉流畅,而且不用doevents。
      

  9.   

    比如说读命令:读D448
    @00FA00000000001018201C00000040B*
    @表开头,00表PLC站号,FA表FINS命令,000000000表网络我不通过以太网直接连的,0101表是读命令,82是D区,01C0是448的十六进制,00BIT位,0004读四个字,0B是校验码,*回车是结束码。
    结果:
    @00FA004000000001010000345736520049000049*
    前面是站号,命令头和网络,0101是命令码,0000是回复码,表示完成,3457365200490000是读到的数据,后面是校验和*回车。和协议有什么关系?
      

  10.   

        谢谢carefire,PLC是有个multiple memory area read,虽然可以一条命令读不同区域,但不能设置每个区域各读几个字,回头再跟欧姆龙确定一下。
        是用一根我焊的线直接连接的,串口对串口。
        这个方法是蛮省时间的,但timer的interval属性要设置好了。你说的设置两个变量是不是用于timer的interval的值啊?
      

  11.   

    LZ:从你叙述的通信协议看,PLC返回的指令有33或42字节长度,为何不做成相同字节长度?
    你使用9600波特率,理论最大传送字节为每秒960字节,大约每字节需1ms,则PLC返回42字节指令的时间至少需42ms,建议你的若轮询指令间隔为100ms,这样每秒可轮询10个地址的指令.如果需要每秒接收更多地址指令,除了提高波特率外,还可修改通信协议约定,将PLC返回指令中不必要的内容取消(如表示网络的部分),也可采用数字数据使用字节数据而非ASCII字符组成)
    其次请检查PLC在收到轮询指令,它反应且回复指令的时间需要多少ms.
    接收代码中尽可能不使用Doevents语句.
      

  12.   


    我的意思是:设置公共缓冲数组,使用事件方式接收,timer1只管发命令,timer2只管处理,设置read_index和write_index,write_index增1,oncomm接收数据写入公共数组,然后timer2使read_index增1,从公共数组读出处理,始终使read_index<=write_index。命令timer1的interval可以:
    (1)设置为最长的plc响应时间
    (2)也可根据每次命令动态修改处理timer2的interval可以固定设置为5~50毫秒。这样的好处:串口异步接收时可以处理上一次结果和界面操作,而且可以做到不用doevents。不过一次oncomm事件后,如果返回很长,串口缓冲不一定就有本次的全部数据,可能被分割到几次事件幸好你的数据好像都以“@”开头而不用太麻烦。
      

  13.   

    楼主:
    timer控件循环地发命令,处理收到的数据。但这样一个timer周期大概要2、3秒
    不会要这么长吧,能否将代码贴出来让我们学习一下?
      

  14.   

    zdingyun:这个协议是根据手册上的hostlink协议,不按它的格式来,PLC不睬你。我看到别人有用字节数据传递的,但那也是ASCII码对应的数据如回车是13。如果自己定协议的话是不是要PLC里的做程序支持啊?LS:我的timer目前设置在500毫秒,具体时间是我自己数的,正准备要实测一下,只是今天在单位忙别的。我的代码写的很不规范的,我都不好意思拿出来。