我用VB写了一个关于MODBUS的协议
可是在接收时产生了问题
我用的是MSComm1_OnComm事件接受的,代码如下:
 Dim nowstring As Variant
     Dim i As Integer
      Select Case MSComm1.CommEvent
          Case comEvReceive     '接收事件
                  '接收缓冲区收到Rthreshold个字符时触发
                  If MSComm1.InBufferCount Then
                          nowstring = MSComm1.Input
                          For i = LBound(nowstring) To UBound(nowstring)
                             InString = InString & CStr(Hex(Val(nowstring(i)))) & " "
                          Next i
                         nowstring = ""
                  end if
比如我发送的数据是 01 04 00 00 00 10 F1 C6
接收的数据应该为01 04 20 04 B2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B1 1B 
可是有时这个数据接收过来是正确的,有时只接受到01 04 20 04 B2 00 00 00
怎样才能正确接收啊?
我设置的MSCOMM的属性为
   MSComm1.Settings = "19200,8,N,1"    
    MSComm1.CommPort =1
    MSComm1.SThreshold = 1
    MSComm1.RThreshold = 1
    MSComm1.InputLen = 0
    MSComm1.PortOpen=true
    MSComm1.InputMode = comInputModeBinary请各位大侠帮忙啊!在下不胜感激!

解决方案 »

  1.   

    设置MSComm1.RThreshold = 37
      

  2.   

    Setting the SThreshold property to 0 (the default) disables the OnComm event for data transmission events. Setting the SThreshold property to 1 causes the Comm control to generate the OnComm event when the transmit buffer is completely empty.If the number of characters in the transmit buffer is less than value, the CommEvent property is set to comEvSend, and the OnComm event is generated. The comEvSend event is fired only once, when the number of characters crosses the SThreshold property. For example, if SThreshold equals five, the comEvSend event occurs only when the number of characters drops from five to four in the output queue. If there are never more than SThreshold characters in the output queue, the event is never fired.
      

  3.   

    to zdingyun()
    接收数据的长度是不固定的
      

  4.   

    Private Sub Form_Load()
        MSComm1.CommPort = 1                   'COM端口
        MSComm1.Settings = "19200,n,8,1"
        MSComm1.InputMode = comInputModeBinary      '采用二进制传输
        MSComm1.InBufferCount = 0   '清空接受缓冲区
        MSComm1.OutBufferCount = 0  '清空传输缓冲区
        'MSComm1.SThreshold = 1      '如果传输缓冲区完全空时产生MSComm事件
        MSComm1.RThreshold = 1      '产生MSComm事件
        MSComm1.PortOpen = True
        Text3 = "" '打开端口
    End SubPrivate Sub MSComm1_OnComm()
    On Error Resume Next
        Dim BytReceived() As Byte
        Dim strBuff As String
        Dim strData As String
        Dim i As Integer
        Dim x As Integer
        Select Case MSComm1.CommEvent
            Case 2
                MSComm1.InputLen = 0
                strBuff = MSComm1.Input
                BytReceived() = strBuff
                For i = 0 To UBound(BytReceived)
                    If Len(Hex(BytReceived(i))) = 1 Then
                        strData = strData & "0" & Hex(BytReceived(i))
                    Else
                        strData = strData & Hex(BytReceived(i))
                    End If
                Next
                Text3 = Text3 + strData
                If Left(strData, 2) = "00" And Len(strData) = 8 Then '接收4字节
                Text1(0).Text = Left(strData, 8)
                Call DataClear
                ElseIf Left(strData, 2) = "01" And Len(strData) = 74 Then '接收37字节
                Text1(1).Text = Left(strData, 74)
                Call DataClear
                End If
    End Select
    End SubPublic Sub DataClear()
        MSComm1.OutBufferCount = 0   '清空发送缓冲区
        MSComm1.InBufferCount = 0
        Text3 = ""
    End Sub
      

  5.   

    to zdingyun()
    我接受的数据不是固定的,这得看我发送的数据是多少
    比如我发送的数据是
    01 04 00 00 00 10 f1 c6
    那么我的数据长度就是10,即16位
    而此时我接受的数据就是16*2=32位
    另外的数据是地址、功能和校验码
    如果我发送的数据是,这里就是37位
    01 04 00 00 00 07 B1 C8 
    那么数据长度就是07 ,即14位
    接收的数据就为28位
    如果再加上其他的数据总共是33位发送和接收的数据都是十六进制
    现在这个问题我已经解决了
    加入了延时,可是我还是不明白为什么加入延时才可以呢?
      

  6.   

    将MSComm1.Settings = "19200,n,8,1"中19200改9600试试。
    发送命令时间间隔调大些。
    RS232串口连接距离不宜过长,可能有干扰。在接收代码中增加判断代码。
    建议返回数据固定字节长,可补足字节长。不回接收出错,字节长尽可能为8的倍数。
      

  7.   

    那你应使用TIMER控件来控制轮询数据。
    Private Sub Timer1_Timer()
        Dim i As Integer
        Static j As Byte
        Dim bytData(1) As Byte
        j = j + 1
        For i = 0 To 1
            bytData(i) = &H0 + j
        Next
        If j >= 4 Then
        j = j - 4
        End If
        Call SendData(bytData)                 '发送
    End Sub
    在窗体初始化设置
        Timer1.Interval = 100 '数字可调,最小55,TIMER控件每秒系统提供18次变化
      

  8.   

    发送数据  01 04 00 00 00 0A 70 0D 
    应该接收到01 04 14 04 B2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7B 67 可是为什么不设断点的时候就接收错误,只有设了断点以后逐步调试才能接收到正确的数据,这是为什么?
      

  9.   

    查下你下位机是用RS232还是RS485。RS232是双工,RS485是单工。
      

  10.   

    是单工的,我都测试了一下
    比如01 04 00 00 00 02 71 CB 
        01 04 00 00 00 06 70 08
        01 04 00 00 00 0A 70 0D
        01 04 00 00 00 0E 71 CE 
        01 04 00 01 00 02 20 0B 
        01 04 00 01 00 06 21 C8
        01 04 00 01 00 0A 21 CD 
        01 04 00 01 00 0E 20 0E
        01 04 00 02 00 02 D0 0B
        01 04 00 02 00 06 D1 C8
        01 04 00 02 00 0A D1 CD
        01 04 00 02 00 0E D0 0E

        01 04 00 0D 00 02 E0 08
        01 04 00 0E 00 02 10 08
    这些接收时必须要设短点才能接收到正确的结果,否则错误
      

  11.   

    所以建议使用TIMER控件来控制轮询数据。我2007-04-11 15:20:53 及2007-04-11 15:58:17的答贴代码可供你参考,祝好运.使用TIMER控件来控制轮询数据实质就是延迟空出间隔来处理MSComm1_OnComm事件的接收.
      

  12.   

    这问题我碰到过,是mscomm控件本身的问题,尤其在不间断发出请求时尤其明显,必须加延迟或者加大传输率,这是我的解决方法
      

  13.   

    呵,感觉楼上的方法虽然能解决问题,却都是治标不治本的方法.这个问题根本就不是一个BUG,而是使用方法的问题.
    如果用TIME等去查询,就失去了使用事件的意义,而且如果上位机工作压力过大的话,很有可以失掉数据,用TIME延时的时间也不好控制,太大了不好,太小了还是会丢数据.实际的根源在于:当你响应ON_COMM时,这时候,很有可能控件已经再接收到了新的数据,此时的数据数目已经不再是你刚进入事件处理程序时取得的数据长度了,所以,删除数据时的依据不能以刚刚进入程序时取得的数据长度为准.就说这么多了,希望对大家有点帮助.
      

  14.   

    串口通讯一般都是单双工的,所以发送以后返回的数据具体是什么内容应该是明确的.个人推荐使用timer,一般设置为100ms就可以了,因为在9600bps速率下,100ms的间隔可以等待大概100bytes的数据,而一般通讯而言,对于单独一次的通讯应该不可能返回超过100bytes的数据吧?在发送的时候设置一个fgSEND,以便在下一个timer事件中直接进行判断这次返回的数据是什么数据,还有使用了timer的话,一定要设置RThreshold = 0,这样能保证把接受缓冲区的数据全部收到程序的Buffer() as Byte字节数组中进行处理.还有,用VB写一般通讯程序,如果使用ONCOMM事件来进行不断通讯的处理的话,程序的其他操作就会比较卡,所以可以考虑用后台ActiveX EXE组件来实现,在前台只要处理一下返回的数据就可以了,然后其他前台的操作也不受通讯的影响,比较不错.我们公司当前的监控管理软件系统就是这么做的.个人观点,请大家多多批评.
      

  15.   

    使用TIMER控件效率是很底的.
    1 检查你的初始化 是否正确, 波特率设置的不要太高建议使用9600,可能232的晶震不能提供这么高的频率
    2 MSComm1.RThreshold 值根据需要设置可以设置的大一些.
    3 用"串口调试助手"调试
    4 如果你是要与单片机(C51 128 )通信应该使用 双字节的16进制编码.
      

  16.   

    在VB6.0中使用datagrid
    怎么样双击表头进行双向排序
    在网上找了一些例子不使用
    不知道怎么写
    有那位兄弟有这方面的事例
    不是在(。NET)