我在做接收由单片机通过串口发送数据的程序
自己定义了延时函数如下  因为接收的数据不是定长的
所以设置 Rthreshold 为 1,接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件
问题就出来了 在接收的数据过多时候超过2W个字节 程序就会在
⑴这里出错 提示溢出堆栈空间  请高手帮忙 ( ⑵ 那里的延时不能去掉 )
Sub TimeDelay(DT As Long)
Dim t As Long
t = GetTickCount()
Do
  DoEvents       ..........................出错的地方.............. ⑴
Loop Until GetTickCount - t > DT
End SubDim buffer As Variant
Dim Receive() As Byte
Private Sub MSComm1_OnComm()Select Case MSComm1.CommEvent
    Case comEvRing
    Case comEvReceive
    
        TimeDelay (200)     .................................⑵         buffer = MSComm1.Input
        BytesReceived() = buffer .........处理数据过程......End SelectEnd Sub

解决方案 »

  1.   

    同时被调用的TimeDelay函数次数太多了, 造成堆栈溢出。个人认为在comEvReceive事件中的延时没有必要,你应该把每次接收到的数据进行缓存,然后判断缓存了的数据是否已经足够进行处理。
      

  2.   

    comEvReceive里 是必须要做延时的 这个是和单片机有关系的 
    其实我也知道是由于调用TimeDelay函数次数太多了, 造成堆栈溢出
    有没有别的延时函数 给推荐一下 ?
      

  3.   

    comEvReceive里 是必须要做延时的 这个是和单片机有关系的 是不是在第一次comEvReceive时, 马上buffer = MSComm1.Input, 接收不到完整的数据包?
    如果是, 则按我上面所讲的办法处理。除非,和单片机的通讯包没有规定格式(通讯协议),那就不好办了。
      

  4.   

    sleep()函数在这里可以用吗? 由于单位不让上网 只有每次将问题带回宿舍来问 也不能试 
    比较郁闷
      

  5.   

    堆栈溢出?
    那是你的数组下标越界,不是doevents的错误
      

  6.   

    Dim buffer As Variant
    Dim Receive() As Byte
    Private Sub Timer1_Timer()
        buffer = MSComm1.Input
        BytesReceived() = buffer
     '.........处理数据过程......
     End SubPrivate Sub MSComm1_OnComm()
        Select Case MSComm1.CommEvent
            Case comEvRing
            Case comEvReceive
                Timer1.Enabled = False
                Timer1.Interval = 200
                Timer1.Enabled = True
        End Select
    End Sub
      

  7.   

    sleep倒是能用的, 不过, 效果不会太好,毕竟VB就一个线程,一Sleep,整个程序就停那儿了。我还是认为那个延时是没有必要的,肯定有办法不用它的。
      

  8.   

    蚜虫的办法应该不错,可以避免掉不少(不是全部)的函数重入。稍作修改:Dim buffer As Variant
    Dim Receive() As Byte
    Private Sub Timer1_Timer()
        Timer1.Enabled = False
        buffer = MSComm1.Input
        BytesReceived() = buffer
     '.........处理数据过程......
    End SubPrivate Sub MSComm1_OnComm()
        Select Case MSComm1.CommEvent
            Case comEvRing
            Case comEvReceive
                Timer1.Interval = 200
                Timer1.Enabled = True
        End Select
    End Sub
      

  9.   

    也就是说 给单片机处理信息的时间 要有延时才可以完成  做过实验 最少也要200MS 
    单片机通讯协议是有的 接收的数据是由每10个字节的小数据包组成的
    数据发送完毕后也有结束符    OnEvReceive事件发生时,应该是单片机已经处理结束并且返回数据的时候了,此时单片机已经不再需要时间去处理信息了,你这个延时,从功能上讲应该是保证在buffer = MSComm1.Input时能接收到一个从单片机发送来的完整的数据包。
      

  10.   

    OnEvReceive事件发生时,应该是单片机已经处理结束并且返回数据的时候了,此时单片机已经不再需要时间去处理信息了,你这个延时,从功能上讲应该是保证在buffer = MSComm1.Input时能接收到一个从单片机发送来的完整的数据包。
    ======================
    而且因为数据包有结束符,所以jadeluo(秀峰) 开始说的办法应该可行
      

  11.   

    OnEvReceive事件发生时,应该是单片机已经处理结束并且返回数据的时候了,此时单片机已经不再需要时间去处理信息了,你这个延时,从功能上讲应该是保证在buffer = MSComm1.Input时能接收到一个从单片机发送来的完整的数据包。其实我这里一直有个疑问, 我设置的 Rthreshold 为 1,应该是接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件的啊   OnEvReceive事件发生时 不一定单片机就把所有的数据发送到缓冲区了吧 ????? (一直有这个疑问的)
      

  12.   

    其实我这里一直有个疑问, 我设置的 Rthreshold 为 1,应该是接收缓冲区收到每一个字符都会使 MSComm 控件产生 OnComm 事件的啊   OnEvReceive事件发生时 不一定单片机就把所有的数据发送到缓冲区了吧 ????? (一直有这个疑问的)我觉得过程应该是单片机计算完毕后一次性把所有数据发出,在这一瞬间触发一连串OnComm事件,只需要在OnComm事件中把收到的每个字符转移到缓冲区里面就可以了,好像没必要延时。
      

  13.   

    情况有可能是这样的:
    时间  单片机       PC
    1     发送一个字节
    2     继续发送     产生OnEvReceive事件
    3     继续发送     开始接收, 此时收到的不止一个字节, 但是不一定是一个完整的通讯包因此,只要制定了通讯包的格式,接收方就应该按照先缓存再处理的方法来比较高效地完成通讯。
      

  14.   

    我觉得过程应该是单片机计算完毕后一次性把所有数据发出,在这一瞬间触发一连串OnComm事件,只需要在OnComm事件中把收到的每个字符转移到缓冲区里面就可以了,好像没必要延时。可我做过实验的 必须加了延时 才可以把数据接收过来  因为在串口调试的时候 好多问题都是试验出来的 明天到办公室先按两位的方法看看能不能解决  实在感谢 舍不得结贴 还想从两位身上学点更多的东西 自己在MSCOMM这个控件方面有好多不清楚  :)
      

  15.   

    情况还有可能是这样的:
    时间  单片机       PC
    1     发送一个字节
    2     继续发送     产生OnEvReceive事件
    3     继续发送     开始处理OnEvReceive事件
    4     继续发送     由于某些原因, 未能立即接收
    .
    .
    .
    n     继续发送     开始接收, 此时收到的不止一个字节, 而且有可能已经是若干个完整的通讯包了反正不管是什么样的情况, 缓存后再按通讯包格式来处理, 总能正确地完成通讯。
      

  16.   

    那这样问吧 比如协议是这样定的A0(头) + 8个字节的数据 + FF(尾)一个小数据包是10个字节组成发送完毕后加一结束符 A1怎么样编写效率就可以高点了  :)    整个数据包 可能上3W个字节  缓冲区的大小是Integer型的也就只能到65535/2 个字节了
      

  17.   

    换用系统timer做的delay函数试试
    sub delay(delaytime as single)
    dim start 
    start=timer
    do while timer<start+delaytime
    doevents
    loop
    end sub
      

  18.   

    应该不是Doevent的问题,估计是你的buffer读取的数据太大,引起的栈空间溢出。
    因为你的buffer为局部变量,是在栈中分配的,当数据很大时,会溢出的。
    当然,执行doevents后,会处理事件队列的其他事件,很可能是其他事件引起的栈溢出,这个问题很难解决阿,应该跟你当时的系统有关系