问这个问题已经是第二次,上次是在单片机板块问,上个月,大约20人回答,都没法解。
这次我要讲得更清楚点。
程序的要求是和一个单片机管理的LCD通讯,通过串口发给它35字节长度的各种报文,接受到“OK”字符串表示成功,接收到“ER”字符串表示错误。
单片机的程序和硬件设计由另一人负责,其实我也不懂那一块。
我用VB编写PC机的软件。
最初我的设计很顺利,单片机串口接线是RS232标准,我用VB里的Form加一个MSCOMM控件轻松完成上面的通讯要求。通讯设置是4800,e,8,1
可是上个月,硬件更换了,接线是485标准,通过转232的接头接到PC机上,其他不变。
却发现我的软件程序无法正确收到"OK"的回应,而只是收到“K”或者“KK”的回应,非常不稳定。
而一个叫“串口调试助手”的著名的程序却是发送接受都很正常,与硬件结合很好。
于是开始了一个月繁杂的调试。
主要是因为我对串口通讯不熟悉,很多参数都是照网上画瓢。
下面是我的一个简单发送HELO呼叫报文的测试程序
HELO呼叫报文的要求是35字节长度,第一字节是128,第二字节是1,剩余的字节都是0。
单片机那边收到HELO呼叫,应该返回“OK”的回应。代码(精简的):
Private Packet(35) as Byte '当前要发送的包
Private instrBuffer As String '接收缓冲区,接收到单片机的回应码'一个发送按钮
Private Sub cmdSend_Click()
Packet(0) = 128
Packet(1) = 1
Packet(2) = 0
Packet(3) = 0
If ComTest.PortOpen = False Then
ComTest.PortOpen = True
End If
ComTest.InputMode = comInputModeText
ComTest.Output = Packet
end Sub'MSCOMM控件ComTest的OnComm事件
Private Sub ComTest_OnComm()
instrBuffer = "" '清空一下
txtInputCount.Text = CStr(ComTest.InBufferCount) '将InBufferCount显示到一个Text里面
instrBuffer = ComTest.Input 'COM的输入直接传给字符串
txtReceive.Text = txtReceive.Text + instrBuffer '将字符串显示在一个Text里面
End SubMSCOMM控件的设置是
.InputMode=comInputModeText
.RThreshold=1
.SThreshold=0
.Inputlen=40 '考虑到接收回慢些
.InBufferSize=1024
.OutBufferSize=512
.Settings="4800,e,8,1"
其余都是默认。可是收到回应的只有一个"K"。
如果把RThreshold=2,那么发送两次才收到一个"KK"。今天下午又写了一个VC的程序,也是和上面的要求一样,调用MSCOMM控件,
竟然可以正确的收到“OK”
实在是不明白。
还有,我们又试着将回应码改成了单字符,即 正确返回是“K”,错误返回是“R”
我的VB测试程序收到的是?
而VC程序仍然正常收到“K”
可以肯定是我的VB程序的思路错了
这些VB代码仅仅是工程里的小部分,现在老板催得急,不可能重新用VC编写工程,而且我的VC语言很弱。
现在我请朋友帮忙,让他用VC写一个lib文件,调用MSCOMM控件的发送和接收,然后我再到VB代码里调用他写的lib里的函数来控制MSCOMM控件。
很失望,很迷茫,很不甘心。
我希望各位能给我指点一下迷津,帮我在VB里面找出错误来。
为什么我只能收到“K”?
为什么同样是MSCOMM控件,VC的程序就能正常收到“OK”?
我真的必须调用VC代码才能控制MSCOMM控件吗?
这次我要讲得更清楚点。
程序的要求是和一个单片机管理的LCD通讯,通过串口发给它35字节长度的各种报文,接受到“OK”字符串表示成功,接收到“ER”字符串表示错误。
单片机的程序和硬件设计由另一人负责,其实我也不懂那一块。
我用VB编写PC机的软件。
最初我的设计很顺利,单片机串口接线是RS232标准,我用VB里的Form加一个MSCOMM控件轻松完成上面的通讯要求。通讯设置是4800,e,8,1
可是上个月,硬件更换了,接线是485标准,通过转232的接头接到PC机上,其他不变。
却发现我的软件程序无法正确收到"OK"的回应,而只是收到“K”或者“KK”的回应,非常不稳定。
而一个叫“串口调试助手”的著名的程序却是发送接受都很正常,与硬件结合很好。
于是开始了一个月繁杂的调试。
主要是因为我对串口通讯不熟悉,很多参数都是照网上画瓢。
下面是我的一个简单发送HELO呼叫报文的测试程序
HELO呼叫报文的要求是35字节长度,第一字节是128,第二字节是1,剩余的字节都是0。
单片机那边收到HELO呼叫,应该返回“OK”的回应。代码(精简的):
Private Packet(35) as Byte '当前要发送的包
Private instrBuffer As String '接收缓冲区,接收到单片机的回应码'一个发送按钮
Private Sub cmdSend_Click()
Packet(0) = 128
Packet(1) = 1
Packet(2) = 0
Packet(3) = 0
If ComTest.PortOpen = False Then
ComTest.PortOpen = True
End If
ComTest.InputMode = comInputModeText
ComTest.Output = Packet
end Sub'MSCOMM控件ComTest的OnComm事件
Private Sub ComTest_OnComm()
instrBuffer = "" '清空一下
txtInputCount.Text = CStr(ComTest.InBufferCount) '将InBufferCount显示到一个Text里面
instrBuffer = ComTest.Input 'COM的输入直接传给字符串
txtReceive.Text = txtReceive.Text + instrBuffer '将字符串显示在一个Text里面
End SubMSCOMM控件的设置是
.InputMode=comInputModeText
.RThreshold=1
.SThreshold=0
.Inputlen=40 '考虑到接收回慢些
.InBufferSize=1024
.OutBufferSize=512
.Settings="4800,e,8,1"
其余都是默认。可是收到回应的只有一个"K"。
如果把RThreshold=2,那么发送两次才收到一个"KK"。今天下午又写了一个VC的程序,也是和上面的要求一样,调用MSCOMM控件,
竟然可以正确的收到“OK”
实在是不明白。
还有,我们又试着将回应码改成了单字符,即 正确返回是“K”,错误返回是“R”
我的VB测试程序收到的是?
而VC程序仍然正常收到“K”
可以肯定是我的VB程序的思路错了
这些VB代码仅仅是工程里的小部分,现在老板催得急,不可能重新用VC编写工程,而且我的VC语言很弱。
现在我请朋友帮忙,让他用VC写一个lib文件,调用MSCOMM控件的发送和接收,然后我再到VB代码里调用他写的lib里的函数来控制MSCOMM控件。
很失望,很迷茫,很不甘心。
我希望各位能给我指点一下迷津,帮我在VB里面找出错误来。
为什么我只能收到“K”?
为什么同样是MSCOMM控件,VC的程序就能正常收到“OK”?
我真的必须调用VC代码才能控制MSCOMM控件吗?
解决方案 »
- 如何将一个网址的页面源代码下载到变量或txt文件中!
- UDP协议中如何传输文件
- 一个关于在vb中把数据库(SQL2000)的数据更新与添加
- 能否用set rs=conn.execute("insert into ...")返回记录集,如果不能...
- 如何判断安装在机器里的office的不同版本?
- 怎么用代码修改控制面版日期格式为yyyy/mm/dd?
- 考研怎么考呀?
- 急急!!!!!!如何在IE中截获其双击事件并得到其要超连接的地址!!!!!!!
- 关于打印预览的问题
- VB真的不知1、2、3 .....谁大???奇怪!
- mscomm这个东东,到底要折磨偶多久,请大家帮帮忙了,谢谢!
- 怎样修改 Datagrid 的列宽(急急急急急急急急急!)
instrBuffer = "" '清空一下instrBuffer = ComTest.Input
txtInputCount.Text = instrBuffer
txtReceive.Text = txtReceive.Text & instrBuffer '将字符串显示在一个Text里面
End Sub
再次比较两者的逻辑是否一样.
一点见解.
我的原来的大工程里的程序代码没加
txtInputCount.Text = CStr(ComTest.InBufferCount)
一样是收到K。to wz19761022
VB 和 VC通用MSCOMM控件,这是在编程平台里能找到的。
instrBuffer = "" '清空一下
Select Case MSComm1.CommEvent
Case comEvReceive
instrBuffer = ComTest.Input
txtInputCount.Text = instrBuffer
txtReceive.Text = txtReceive.Text & instrBuffer '将字符串显示在一个Text里面
Case comEventRxOver
'接 收 缓 冲 区 溢 出
ComTest.InBufferCount = 0
instrBuffer = ComTest.Input
Debug.Print "接 收 缓 冲 区 溢 出"
Case comEventTxFull
'发 送 缓 冲 区 溢 出。
ComTest.OutBufferCount = 0
instrBuffer = ComTest.Input
Debug.Print "发 送 缓 冲 区 溢 出"
Case comEventBreak
Debug.Print "接收到一个中断信号"
instrBuffer = ComTest.Input
end select
End Sub
'你试一下看会打印出什么东西出来
dim a() as byte
a=mscomm1.input 'a(0)=asc('o')
'a(1)=asc('k')
关注
单片机部分都是以16进制收发数据,
有什么不对吗?to shangfc(指南针)
见过byte数组作接收的吗?我没用过,好像这样会出现类型错误的提示!!!
楼主看一下是不是MSCOM的设置有问题,我们都是用的二进制方式接收的
email:[email protected]
可以和楼主交流一下
.InputMode = comInputModeBinary
用文本方式接收的话,出现高位为1的字符,下一个字符就被吃掉了,接收的时候用字节
Dim Rec() as Byte
Recv = .Input
如果接收的内容包含多余的东西,找单片机的编制者就好了
你说的:
.InputMode = comInputModeBinary
用文本方式接收的话,出现高位为1的字符,下一个字符就被吃掉了,接收的时候用字节
Dim Rec() as Byte
Recv = .Input昨天我又进一步比较了我的VB程序和“串口调试助手”的区别
我发现SThreshold=0和SThreshold=1也有关系,究竟该设置哪一个呢?
还有就是InputMode的选择,VC的程序都用Binary接收,而我的VB程序都是Text接收
变成Binary形式真的能行吗?
那么我的接受代码该怎么写呢?
如下:
Dim Rec(2) as Byte
Rec=ComTest.Input
是吗?
我在顶层的帖子上说了:单片要收到35字节的报文才能返回返回“OK”或者“ER”
我做了一个假设
单片机的汇编程序接受了头两个字节的数据,比对第一字节=128,第二字节=1,就返回OK
而这时剩余的33字节还完全传送完毕,这样返回字OK就和剩余的发送字节冲突了,造成了丢失?
那这种丢失为什么偏偏少了头字节呢?
还有我们修改了返回字成为K,竟然收到“?”问号--表示奇偶校验错误,为什么?也用上面的假设解释不清楚。还请帮我分析一下。
Private Sub ComTest_OnComm()
instrBuffer = "" '清空一下
.....
问题就在这个清空一下
因为你的 MSCOMM控件的设置是
.InputMode=comInputModeText
.RThreshold=1也就是说收到一个字符就会产生一个OnComm事件,
那么, 在你收到OK的"O"的时候, 你取了并显示在TEXT里,并清了, 接着收到"K",你又取了显示在TEXT里,
那么后面的"K"是不是就会把前边的"O"给盖掉了成了"K"了呢?
建议如下:
Private Sub ComTest_OnComm()
if ComTest.inBufferCount<2 then
Exit sub '没有两个以上的字符就等待下一次
else
instrBuffer = "" '清空一下
instrBuffer = ComTest.Input
txtInputCount.Text = instrBuffer
txtReceive.Text = txtReceive.Text & instrBuffer '将字符串显示在一个Text里面
endif
End Sub或则:
Private Sub ComTest_OnComm()
dim sngTimer as single
sngTimer=Timer+1
Do while sngTimer>Timer ''等上一秒种, 确保接收完毕
doevents
loop instrBuffer = "" '清空一下
instrBuffer = ComTest.Input
txtInputCount.Text = instrBuffer
txtReceive.Text = txtReceive.Text & instrBuffer '将字符串显示在一个Text里面
end sub
Option Explicit
Dim Out() As Byte '接收var中的值
Dim var As Variant '接收MSC.input中的数值
Dim nRece As Integer '计算MSC.inputbuffer的个数
Dim i As Integer, j As Integer '随即变量,计算循环
Dim DELAY As SinglePrivate Sub cmdSend_Click() '发送按钮
Dim packet(35) As Byte
For i = 0 To 34
packet(i) = 0
Next i
packet(0) = 128
packet(1) = 1
DELAY = CSng(txtDelay.Text)
If Not MSC.PortOpen Then
MSC.PortOpen = True
End If
MSC.Output = packet
End SubPrivate Sub Form_Load() ‘form加载
ClearText
With MSC
.CommPort = 1 '设置Com1为通信端口
.Settings = "4800,E,8,1"
.InBufferSize = 40 '设置缓冲区接收数据为40字节
.InputLen = 2 '设置Input一次从接收缓冲读取字节数为2
.RThreshold = 1 '设置接收一个字节就产生OnComm事件
.SThreshold = 1 '发送完毕就产生OnComm事件
End With
DELAY = 0#
txtDelay.Text = Format(DELAY, "00.00")
Label1.Caption = Label1.Caption + " " + CStr(MSC.Settings)
End Sub
Private Sub ClearText() '清空Text1
Text1.Text = ""
End Sub
Private Sub Command1_Click() 'reset按钮
ClearText
nRece = 0 '计数器清零
With MSC
.InputMode = comInputModeBinary '设置数据接收模式为二进制形式
.InBufferCount = 0 '清除接收缓冲区
If Not .PortOpen Then
.PortOpen = True '打开通信端口
End If
End With
End SubPrivate Sub MSC_OnComm()
DelayTime '‘用来延续时间
ClearText
With MSC
Select Case .CommEvent '判断通信事件
Case comEvReceive: '收到Rthreshold个字节产生的接收事件
var = Null
var = .Input
Out = var
Text1.Text = Text1.Text + Str(Out(0)) + " " + Str(Out(1))
Case Else
' .PortOpen = False
End Select End WithEnd Sub
Private Sub DelayTime() ’延时函数
Dim bDT As Boolean
Dim sPrevious As Single, sLast As Single
bDT = True
sPrevious = Timer '(Timer可以计算从子夜到现在所经过的秒数,在Microsoft Windows中,Timer函数可以返回一秒的小数部分) Do While bDT
If Timer - sPrevious >= DELAY Then bDT = False
Loop
bDT = True
End Sub测试结果:
测试没有延时和多种延时情况下都是收到“75 0”,按 reset按钮后发送,出现对话框“运行时错误‘9’下标越界”,继而关闭。怎么办啊?我觉得写的代码已经使用了二进制接收了阿
大家帮忙啊
ClearText
nRece = 0 '计数器清零
With MSC
If Not .PortOpen Then .PortOpen=False
.PortOpen = True '打开通信端口
.InputMode = comInputModeBinary '设置数据接收模式为二进制形式
.InBufferCount = 0 '清除接收缓冲区
End With
End SubPrivate Sub MSC_OnComm()
DelayTime '‘用来延续时间
ClearText
With MSC
Select Case .CommEvent '判断通信事件
Case comEvReceive: '收到Rthreshold个字节产生的接收事件
var = Null
Out = .Input
for i=lbound(Out) to Ubound(Out)
Text1.Text = Text1.Text + chr(Out(i)) + " "
next
Case Else
' .PortOpen = False
End Select End WithEnd Sub
问题终于解决了,我的程序可以合理的收到返回字“OK”了。
我犯了一个严重的数组长度的错误,我把VB语言里的数组边界和VC里面的边界混淆了。
在顶部的问题帖子里面,我有声明语句
Private Packet(35) as Byte '当前要发送的包
其实这样是不对的,在vB里面这表示36个元素的Byte数组,数组的游标是0到35
而MSCOMM1.Output=Packet
就相当于发送了36字节的helo报文,
在下位机,汇编代码里计数35字节以后就返回OK,
于是发送的第36字节和返回字的第一字节“抵触”了
无论如何也收不到今天在测试的时候,我看vodlinux写给我的代码里面把packet数组定义为
dim packet(34) as byte,我忽然意识到自己的错误。
修改了数组的边界,Packet(34),
inputmode=Text
inputlen=2
Rthreshold=1
Sthreshold=1
一切问题都搞定了!成功了!
万岁!实际上,我并没有完全明白,
因为项目的头两个月用RS232的时候,我也是声明Packet(35),多一个字节,仍可以正常通信,
如今改了RS485,我的Packet(34)才能收到OK返回字,而Packet(35)就只能收到K
谁能给再详细解释一下?
http://community.csdn.net/Expert/topic/3486/3486032.xml?temp=.5334131