一台计算机有10几个串口(RS485),每个串口设备接10台Modbus的设备(总线通讯),如果我在这台电脑上同时连接这些设备的话,就会对10个COM口进行读操作,我现在的方案是:
由于每个串口所连接的设备数量和型号相同,所以,我写一个类模块,对单个串口所连接的设备进行通讯和数据处理。然后在主程序中创建10个类实例(其中内部参数不同)。
但是问题是,运行程序的时候,我感觉电脑慢了下来,我不知道实例化10个类的时候,这个主程序是不是还是单线程的,这10个类实例运行的时候还是占用这一个单线程的队列,如果我把这10个类写成10个exe程序,然后再运行的话是不是会好些,这是我的想法。我觉得慢下来应该是单线程满负荷或者是超负荷运行造成的,各位大侠,请给点意见,绝不吝啬分。

解决方案 »

  1.   

    VB 是单线程的,感觉满是因为串口本身慢。做成ActiveEXE 的话会好点。
    建议使用支持多线程的开发工具。
      

  2.   

    好多的设备啊,10几个串口,每个串口10个设备,合起来有100多个设备,真牛啊 :)是单线程运行的
    你可以试试将串口封装为 activex.exe,工程属性中设置为多线程运行,并且要使用事件回调技术(如果使用等待,用户端则会在调用返回前被挂起)
      

  3.   

    类事件封装成activeexe吗?可否介绍一下实现方法或者例子之类,感激
      

  4.   

    最根本的问题是,串口通讯的速度与 PC 代码的运行速度相差好多数量级。当你的程序以阻塞方式一一与之通讯时,如果设备很多,当然会感觉到慢。1 既然是 RS485 总线,发送命令可以考虑广播方式。2 即使是逐台设备发送命令,也不要立即读取应答。因为这需要等待设备处理完成,累积的时间也很可观。你把通讯分成两轮次,即命令轮次和应答轮次。当你回到第一台设备取应答时,它已经利用了你向其他设备发送命令的时间来进行处理。3 不要用 VB 中的 MSComm 控件来做 RS485 操作,最好用 VC++ 写 API DLL 调用。因为控件在地址模式和数据模式之间相互切换时,需要先禁用,再切换,再启用,会很慢。两者的差距很大。4 其实可以只用一个串口,通过 RS485 Hub 级联的方式把设备都连进来。因为 PC 上的串口并不具备自动缓存数据和命令以自行操作的功能,多了也并不快。如果你能用单片机自己搞一种代理接口,让它来自动与设备交互,然后把缓存的数据传给你,那就值得用多个串口。就好比你只管理十几个工头,让他们去管理工人。
      

  5.   

    ActiveX EXE 是与主程序运行与不同进程的部件,两者运行基本上互不影响,并且可以使用事件或者回调函数向调用者反馈信息,建议你仔细看一下vb的帮助文件,里面很仔细的讲了如何创建ActiveX EXE部件,你只要按照他说的做一遍,就知道是怎么回事了。
      

  6.   


    请介绍一下广播方式的实现方法,因为设备的地址和现场的实际情况,网络结构不能更改了,而且我现在还只对VB的MScomm熟悉一点,请介绍下通讯广播的方法,使用MSCOMM怎么实现?谢谢,
      

  7.   


    是这样,封装成activex exe
    详细你要看MADN,里面有个使用回调的控制咖啡炉的例子,讲的很详细
      

  8.   


    广播需要设备能支持广播,你要看设备是否能接受广播,广播就是发送0地址数据。Modbus协议是一种应答式协议,主机发出功能及参数,从机马上应答;在一条总线上,一个时刻,主机只能一台从机通信,应该不适合使用广播。
      

  9.   

    对于VB而言,不管你是10个串口,还是1个串口,不管你是1个下位机还是100个下位机,你每次都只能通信一个对象,原因有二。
    1、VB是单线程的
    2、Moudle Bus通信每次只能读取一个下位机。再发表一点不成熟的看法,像楼主这样的情况,不管有多少个串口,我们就管计算机连接的下位机数量,共计100个以上的下位机,如果每个下位机通信占用20ms,那么读完一次也是2s时间,实际时间开销会比这大,建议楼主将串口通信代码放到Timer中,且区别对待,对不精要的数据读取时间间隔放宽些,减少通信时间开销,此外,不要采用OnComm方式通信,发送了命令后等待的方式,并且在等待的循环体中添加DoEvents来释放CPU资源,这样可以有效的防止程序界面“假死”的现象。再者,在硬件上,你可以考虑减少串口,采用 RS485 HUB,把下位机数据缓存在HUB上,这样也能有效的提高通信效率。这样处理,时效性会大幅提高,但成本可能也会提高不少。
      

  10.   

    我用的是MOXA的串口服务器,以太网接口至计算机的,一个服务器带16个串口,通讯程序试过很多方式,感觉凭借代码的优化不能显著提高程序的整体运行速度。另外,发送之后等待的方式我也试过,但是每个串口设备的通讯指令不同,有的是读,有的是写,每个循环也不是相同的,我只能在返回的buff中找出具体的数据段和数据标记。这里感谢各位参与讨论的兄弟,明天早上结贴,如有必要再开一贴讨论,感谢分再结。
      

  11.   

    这个对数据处理的区分就非常重要了,可已定义布尔变量来标记写,比如对地址是10的下位机要写,那么设置标记下位机10写的布尔变量为True,这样在Timer中就能判断并写。此外,你可以把Timer 的时间间隔设置为50ms,或者更低,大致的格式如下:
    Option Explicit
    Dim bolWrite(0 To 99) As Boolean    '写下位机标志变量,分别对应1~100个下位机
    Dim intReadNo As Integer            '读取下位机的标识,0~99,分别对应1~100下位机
    Private Sub Timer1_Timer()
        Dim intP As Integer
        For intP = 0 To 99
            If bolWrite(intP) Then
                '写下位机
            End If
        Next intP
        '读下位机
        ReadXiaWeiji (intReadNo)
        intReadNo = (intReadNo + 1) Mod 100 '这个是关键,更新读取对象
    End Sub
      

  12.   

    intReadNo = (intReadNo + 1) Mod 100
    这一句不错,循环,我用的是:A=iif(A=100,1,A+1)兄弟你的思路我知道的,很感谢,通讯设备有一些是自定义的协议,大部分是Modbus,弄起来比较麻烦,现在通讯还算是畅通的,没什么别的问题,就是VB的单线程把程序速度拖慢了,我实例化了10个通讯的类模块,其实还是单线程,只是操作起来方便了些而已。所以我想换个方式来实现
      

  13.   

    我记得Moxa 的串口服务器 可以设置为TCP Server 模式,你就可以直接用网络访问了。
      

  14.   

    我也遇到同样的问题,不太理解用mscomm控件的oncomm事件在初始化的时候如何设置
    InputLen,InBufferCount,RThreshold的参数,触发oncomm后接收数据放在timer里面还是在oncomm()里面处理呢,我是用timer1自动发送请求指令轮询8个串口,每个串口下面有三个设备,如何用timer2来判断数据是否接受完毕呢?