请教下大家个问题 :我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;
}
下面是通信协议 格式:
标志(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;
}
因为同下位机通讯的时候
速度比较慢 有时候还会阻塞
所以vb会发呆,因为他在等自己发出的命令得到回应
所以你可以用doevents把这个操作还给系统省的看起来那么卡这样就需要关闭程序重新打开或者干脆就打开说串口占用了
这样的情况应该是你关闭程序的时候是用end的方式,你没有释放占用的串口资源
再就是不采用end,怎么样来释放占用的串口资源 ?
转让控制权,以便让操作系统处理其它的事件。
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
是否用了 Timer 循环查询?
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
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
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
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
zdingyun哥这样加上确实是有一定的道理的。
zdingyun哥这样加上确实是有一定的道理的。
这样把,抛弃前面的东西,给你一个串口调试器的代码吧,你按照它的来写,绝对错不了。把通信原理搞通了,就好说了。
http://download.csdn.net/source/1262066你在调试过程中有没有观察过CPU的利用率?是否利用率很高?
建议你单步调试,看看问题出在哪一步。这样就可以有的放矢了。
不知道我的这个有问题没有(我给单片机发的全是数值):
Private Sub MSComm1_OnComm()
Dim bytInput() As Byte
Dim intInputLen As Integer
Dim n As Integer
Dim teststring As String
End Sub
2、“另一个建议通信单独做个窗体,通过全局变量传递数据.这样有个好处,可以定时关闭通信窗体,并瞬间后加载通信窗体,可避免通信出错导致的串口假死. ”---zdingyun哥,你那有这样通信的例子吗?能否QQ共享下,我的QQ1140011764(加入注:zdingyun)。谢谢!
向你学习!
敬礼!
格式:
标志字节(帧首) + 命令字节 + 数据参数字节 + 帧尾字节
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是通信窗体
能否针对你下面的东西给我发个这样的工程看看!我的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
(阿根廷巫师) 我给你发私信了!呵呵