请教下大家个问题 :我VB编写exe界面,用于与下位机mega16进行通信,界面有时候就不好使,现象是这样的:有时候点击一个控件,点击另外个控件就不行,点不了,或者要点击两次, 这样就需要关闭程序重新打开或者干脆就打开说串口占用了,这样唯一的办法就得重启电脑(在任务管理器里删除我VB生成的exe都删除不了)。一点规律都没有。请大伙分析下是什么原因?在此非常感谢! 
                                                                                                下面是通信协议 格式: 
标志(3字节) 数据长度(1字节) 命令(1字节) 参数(若干字节) 
协议内容 1.平台上升 
  AA AA AA   FF   01  XX   XX;第一组两字节代表脉冲频率数 
     
2.平台下降 
  AA AA AA    FF 02  ;不发送脉冲数 
3.开始搅拌(开直流电机) 
  AA AA AA   FF  03 XX XX      XX     XX;第一组两字节是运行秒数 ,第二组字节代表方向: 01正向 02反向 03正反转,第三组对应的拖拉条的值,即调加减速的值,与下位机相对应的是j值。 4.停止搅拌(关直流电机) 
  AA AA AA  FF 04 5.开与关PORTA口的部分IO口的命令 
  AA AA AA  FF  05   XX ;这个字节XX如果是92对应开始注入液体“开”(PORTA=0x92),9A对应开始停止注入“关”(PORTA=0x9A),24对应开始冲散液体“开”(PORTA=0x24),1C对应开始停止冲散“关”(PORTA=0x1C),16对应开始抽取液体“开”(PORTA=0x16),1E对应开始停止抽取“关”(PORTA=0x1E)。 
                                                  下面是下位机针对平台上升的部分 
case 0x01:  
                                { 
                                        unsigned char StepNum1= getcharWithTime(0xfffffff ,&Err); 
                                        if(Err==0) 
                                        { 
                                                state=0; 
                                                break; 
                                        } 
                                        unsigned char StepNum2= getcharWithTime(0xfffffff ,&Err); 
                                        if(Err==0) 
                                        { 
                                                state=0; 
                                                               break; 
                                        } 
                                                       if(StepMove( StepNum1*255+StepNum2, 0)) 
                                                putstr("\xaa\xaa\xaa\xff\x01"); 
                                        else 
                                                putstr("\xaa\xaa\xaa\xff\x00"); 
                                        state=0; 
                                        break; 
                                } 

解决方案 »

  1.   

    是这样的
    因为同下位机通讯的时候
    速度比较慢 有时候还会阻塞
    所以vb会发呆,因为他在等自己发出的命令得到回应
    所以你可以用doevents把这个操作还给系统省的看起来那么卡这样就需要关闭程序重新打开或者干脆就打开说串口占用了
    这样的情况应该是你关闭程序的时候是用end的方式,你没有释放占用的串口资源
      

  2.   

    楼上能否把doevents得运用说具体点 ;
    再就是不采用end,怎么样来释放占用的串口资源 ?
      

  3.   

    DoEvents应用
      转让控制权,以便让操作系统处理其它的事件。
      DoEvents 函数会返回一个 Integer,以代表 Visual Basic 独立版本中打开的窗体数目,例如,Visual Basic,专业版,在其它的应用程序中,DoEvents 返回 0。
      DoEvents 会将控制权传给操作系统。当操作系统处理完队列中的事件,并且在 SendKeys 队列中的所有键也都已送出之后,返回控制权。
      DoEvents 对于简化诸如允许用户取消一个已启动的过程 — 例如搜寻一个文件 — 特别有用。对于长时间过程,放弃控制权最好使用定时器或通过委派任务给 ActiveX EXE 部件来完成。以后,任务还是完全独立于应用程序,多任务及时间片由操作系统来处理。
      小心 确保以 DoEvents 放弃控制权的过程,在第一次 DoEvents 返回之前,不能再次被其他部分的代码调用;否则会产生不可预料的结果。此外,如果其它的应用程序可能会和本过程以不可预知的方式进行交互操作,那么也不要使用 DoEvents,因为此时不能放弃控制权。
      使用 DoEvents
      尽管 Timer 事件是后台处理的最好工具,对耗时极多的任务,情况更是如此,但是,DoEvents 函数还是提供了一种取消任务的简便方法。例如,下列代码将显示一个 "Process" 按钮,单击这个按钮时,它将变成 "Cancel" 按钮。再次单击按钮又将中断正在执行的任务。可以参考
    http://baike.baidu.com/view/327466.htm
      

  4.   

    而且你这个看起来是vc啊怎么说是vb
      

  5.   


    是否用了 Timer 循环查询?
      

  6.   

    可能有干扰的存在,导致CPU占用率100%,从而出现死机,建议楼主用串口调试器先把通信调好了,再写程序。这是一个很好的调试串口通信的习惯。
      

  7.   

    我已经用串口调试器调试好了得 随便发送数据 就是与下位机容易跑飞 今天请教一个老师说 可能是我下面的数组的问题 就是发送数据的数组出问题了,大家看看:
    Private Sub Command20_Click()
        Dim Temp As String
        'Dim Temp1 As String
        'Dim Temp2 As String
        'Dim longth As Byte
        Dim buff_out() As Byte
        ReDim buff_out(6)
        buff_out(0) = &HAA
        buff_out(1) = &HAA
        buff_out(2) = &HAA
        buff_out(3) = &HFF
        buff_out(4) = &H1
        Open App.Path & "\2.txt" For Input As #2
        Line Input #2, Temp
        Close #2
        buff_out(6) = Temp Mod 256
        buff_out(5) = (Temp - buff_out(6)) / 256
       If MSComm1.PortOpen = False Then
          Label1.Caption = "您的串口现在是关闭状态,请先打开串口"
            Else
           'Temp = Text2.Text
           'longth = strHexToByteArray(Temp, bytSendByte())
              'If longth > 0 Then
               MSComm1.Output = buff_out
              'MSComm1.Output = bytSendByte
              'End If
            Label1.Caption = ""
           'MSComm1.Output
       End If
    End Sub
      

  8.   

    Private Sub Command20_Click()
        Dim Temp As String
        Dim buff_out() As Byte
        ReDim buff_out(6)
        buff_out(0) = &HAA
        buff_out(1) = &HAA
        buff_out(2) = &HAA
        buff_out(3) = &HFF
        buff_out(4) = &H1
        Open App.Path & "\2.txt" For Input As #2
            Line Input #2, Temp
        Close #2
        'Temp = "32767"
        If Val(Temp) < 32768 Then
            buff_out(6) = Temp Mod 256
            buff_out(5) = (Temp - buff_out(6)) / 256
        End If
        If MSComm1.PortOpen = False Then
          Label1.Caption = "您的串口现在是关闭状态,请先打开串口"
        Else
            MSComm1.Output = buff_out
            Label1.Caption = ""
        End If
    End Sub
      

  9.   

    Private Sub Command20_Click()
        Dim Temp As String
        Dim buff_out() As Byte
        ReDim buff_out(6)
        buff_out(0) = &HAA
        buff_out(1) = &HAA
        buff_out(2) = &HAA
        buff_out(3) = &HFF
        buff_out(4) = &H1
        Open App.Path & "\2.txt" For Input As #2
            Line Input #2, Temp
        Close #2
        'Temp = "32767"
        If Val(Temp) < 32768 Then
            buff_out(6) = Temp Mod 256
            buff_out(5) = (Temp - buff_out(6)) / 256
            If MSComm1.PortOpen = False Then
              Label1.Caption = "您的串口现在是关闭状态,请先打开串口"
            Else
                MSComm1.Output = buff_out
                Label1.Caption = ""
            End If
        End If
    End Sub
      

  10.   

    我看zdingyun哥你就加上这一句“If Val(Temp) < 32768 Then”有什么意义呢?应该没有多大的变化吧?
      

  11.   

    代码有误,Temp你定义为String,在计算中须用Val函数转换为数值,且它的值必须在65536以下,不然
    buff_out(5) = (Temp - buff_out(6)) / 256
    会报溢出错误.
    Private Sub Command20_Click()
        Dim Temp As String
        Dim buff_out() As Byte
        ReDim buff_out(6)
        buff_out(0) = &HAA
        buff_out(1) = &HAA
        buff_out(2) = &HAA
        buff_out(3) = &HFF
        buff_out(4) = &H1
        Open App.Path & "\2.txt" For Input As #2
            Line Input #2, Temp
        Close #2
        If Val(Temp) < 65536 Then
            buff_out(6) = Temp Mod 256
            buff_out(5) = (Temp - buff_out(6)) / 256
            If MSComm1.PortOpen = False Then
              Label1.Caption = "您的串口现在是关闭状态,请先打开串口"
            Else
                MSComm1.Output = buff_out
                Label1.Caption = ""
            End If
        End If
    End Sub
      

  12.   

    可是我问清华大学计算机系的老师说是定义了“ Dim buff_out() As Byte”,是这个buff_out() 数组出的问题,以至于让VB跑飞了。
    zdingyun哥这样加上确实是有一定的道理的。
      

  13.   

    可是我问清华大学计算机系的老师说是定义了“ Dim buff_out() As Byte”,是这个buff_out() 数组出的问题,以至于让VB跑飞了。
    zdingyun哥这样加上确实是有一定的道理的。
      

  14.   

    还有我的这个Dim buff_out里的Dim只是局部定义吧?只是在这个Command20_Click事件里执行吧,因为我其他的比如Command21_Click我也是定义一样的buff_out,而没有重新取名为buff_out1,我觉得这个是没有影响的吧?
      

  15.   

    什么叫跑飞了?!不理解。
    这样把,抛弃前面的东西,给你一个串口调试器的代码吧,你按照它的来写,绝对错不了。把通信原理搞通了,就好说了。
    http://download.csdn.net/source/1262066你在调试过程中有没有观察过CPU的利用率?是否利用率很高?
      

  16.   

    没有观察过CPI的利用率  不过如果程序跑飞了(就是VB不受鼠标控制了,鼠标由箭头形状变为两个倒扣的杯子形状)此时去任务管理器里想试图删除我的VB.exe文件都删不掉,删不掉的话再次打开就说串口占用了,这样的后果就必须重新启动计算机。
      

  17.   

    估计你的CPU利用率此时会很高!100%
    建议你单步调试,看看问题出在哪一步。这样就可以有的放矢了。
      

  18.   

    没有 我刚才看了下 只有2% 很低的 
    不知道我的这个有问题没有(我给单片机发的全是数值):
    Private Sub MSComm1_OnComm()
        Dim bytInput() As Byte
        Dim intInputLen As Integer
        Dim n As Integer
        Dim teststring As String
    End Sub
      

  19.   

    1、如zdingyun哥说的 ,但是我有的就只有5个字节,按照你说的不足9个的是不是就用00,直到添加到9个字节为止啊;
    2、“另一个建议通信单独做个窗体,通过全局变量传递数据.这样有个好处,可以定时关闭通信窗体,并瞬间后加载通信窗体,可避免通信出错导致的串口假死. ”---zdingyun哥,你那有这样通信的例子吗?能否QQ共享下,我的QQ1140011764(加入注:zdingyun)。谢谢!
    向你学习!
    敬礼!
      

  20.   

    LZ:一般数据帧按固定长度,有帧首字节,帧尾字节,命令字节等.除首尾是固定的字符.
    格式: 
    标志字节(帧首)  +  命令字节 + 数据参数字节    +    帧尾字节
            2字节        2字节         4字节             1字节协议内容 
    1.平台上升 
      &HAA &HAA  &HFF  &H1  &HXX  &HXX  &H0  &H0  校验和(或&HFF)
        
    2.平台下降 
      不发送脉冲数 
      &HAA &HAA  &HFF  &H2  &H0  &H0   &H0  &H0  校验和(或&HFF)3.开始搅拌(开直流电机) 
      &HAA &HAA  &HFF  &H3  &HXX &HXX  &HXX &HXX 校验和(或&HFF)4.停止搅拌(关直流电机) 
      &HAA &HAA  &HFF  &H4  &H0  &H0   &H0  &H0  校验和(或&HFF)5.开与关PORTA口的部分IO口的命令 
      &HAA &HAA  &HFF  &H5  &HXX  &H0   &H0  &H0  校验和(或&HFF)
    关于建议2:
    Option ExplicitPrivate Sub Command1_Click()
        frmmain.Show
    End SubPrivate Sub Form_Load()
        Timer1.Interval = 500
    End SubPrivate Sub Timer1_Timer()
        If Label1.Caption <> CStr(Time) Then
            Label1.Caption = Time$
            frmmain.Caption = "串口接收发送" & Space(60) & Date$ & Space(6) & Time$
            If Mid(Time$, 7, 2) = "15" Or Mid(Time$, 7, 2) = "45" Then
                Unload frmmain
            End If
        End If
    End Sub
    'frmmain是通信窗体
      

  21.   

    恩 好的 麻烦zdingyun哥早晨起来就帮我解答 非常感谢
      

  22.   

    zdingyun
    能否针对你下面的东西给我发个这样的工程看看!我的QQ上面有,即QQ1140011764(加入注:zdingyun)。谢谢!
    Option ExplicitPrivate Sub Command1_Click()
        frmmain.Show
    End SubPrivate Sub Form_Load()
        Timer1.Interval = 500
    End SubPrivate Sub Timer1_Timer()
        If Label1.Caption <> CStr(Time) Then
            Label1.Caption = Time$
            frmmain.Caption = "串口接收发送" & Space(60) & Date$ & Space(6) & Time$
            If Mid(Time$, 7, 2) = "15" Or Mid(Time$, 7, 2) = "45" Then
                Unload frmmain
            End If
        End If
    End Sub
      

  23.   

    Veron_04
     
    (阿根廷巫师) 我给你发私信了!呵呵