VB 的InBufferCount的值会变化

Tsunami87 2009-04-20 10:42:05
单片机发送10个字节到电脑
每次都是一样的;
但发现InBufferCount的值会变化
这是变化规律:
InBufferCount =10
第1次数据:0,22,22,3,4,5,6,7,8,9
直到
InBufferCount =10
第10次数据:0,22,22,3,4,5,6,7,8,9
InBufferCount =16
第11次数据:6,7,8,9,0,22,22,3,4,5
InBufferCount =12
第12次数据:8,9,0,22,22,3,4,5,6,7
InBufferCount =10
第13次数据:8,9,0,22,22,3,4,5,6,7
直到
InBufferCount =10
第20次数据:8,9,0,22,22,3,4,5,6,7
第一次的是对的

这是mscomm的设置:
With MSComm1
.InputMode = comInputModeBinary

.InputLen = 1
.Settings = Text2.Text
.InBufferSize = 1000
.RThreshold = 10
.SThreshold = 10
.CommPort = Val(Text1.Text)
.PortOpen = True
End With

text2.text是
9600,n,8,1


接收处理代码
Dim datas0, d(100) As Byte, space As Long, angle As Integer, count As Long
Static datas1, c, t, tt As Byte
Static datas2, datas3, datas4, datas5 As Byte
Dim Buffer As Variant

If MSComm1.CommEvent = 2 Then
count = MSComm1.InBufferCount
MSComm1.InputLen = 10'必须设置为1
Buffer = MSComm1.Input
MSComm1.InBufferCount = 0

For i = LBound(Buffer) To UBound(Buffer)
d(i) = Buffer(i)

Next i

Debug.Print "0xff"
Debug.Print count
For i = 0 To 5
datas0 = d(i)
Debug.Print d(i)
c = c + 1

If c = 6 Then '连续取6次数据

x = x + 1
space = datas2 * 10 + datas1 * 1000 + datas3
angle = Int((datas4 * 256 + datas0) * 0.087890625)

'网络发送
If netsend = True Then
Winsock1.SendData &HFF000000
Winsock1.SendData angle '步进电机步进计数
Winsock1.SendData space
Winsock1.SendData datas5
End If

Label2.Caption = Str(datas1) + "M" + Str(datas2) + "CM" + Str(datas3) + "MM"
Label3.Caption = Str(angle) + "°"
Label10.Caption = "当前目标速度:" + Str(datas5) + "M / H"
drawradar space, angle

c = 0
t = 0
End If

If c = 1 Then datas1 = datas0 '只在第一次时取数据,取米
If c = 2 Then datas2 = datas0
If c = 3 Then datas3 = datas0
If c = 4 Then datas4 = datas0
If c = 5 Then datas5 = datas0



Label7.Caption = "当前数据:" + Str(datas0)
Next
MSComm1.Output = rcomm'发送数据通知单片机,电脑准备好
DoEvents
End If
顺序的错误导致不能提取到正确的信息,很急,请帮帮忙
...全文
1070 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tsunami87 2009-04-22
  • 打赏
  • 举报
回复
其实我的程序还是有点问题!在高速的情况下(大约30个数据包每秒,400字节每秒左右),容易出现错误的数据包!慢了就一点问题没有~
Tsunami87 2009-04-22
  • 打赏
  • 举报
回复
谢谢问题基本搞定了。就是先接收到数组中,然后在判断数组有没有完整的数据包,没有就继续接收,有就分离出来。

VB串口通信,以前都是比较简单的,现在做复杂点的,出了很多问题,所以发了很多贴来问。

谢谢各位了~~ 特别是Tiger_Zhao 兄和zdingyun 兄的指点!!!
Tiger_Zhao 2009-04-21
  • 打赏
  • 举报
回复
单片机发送的任何数据都会被接收到Input中,而 InBufferCount = 0 只是清除当前已收到的数据。
如果控制得不好,就会出现这种情况:
前一批数据(假定总数为10)刚接收一部分(假定收取了6),你执行了清除 Input 操作。
那么剩余的数据(数量4)会继续接收到 Input 中,最后 InBufferCount = 4,由于没有达到 RThreshold = 10 的长度,不会触发 OnComm 事件。
当下批数据(假定总数为10)接收到(长度为6)的部分后,InBufferCount = 1,触发 OnComm 事件。
在你响应 OnComm 事件时,由于还有后续的数据(长度为4),它们可能部分或全部被收到,所以 InBufferCount 的值在 [10, 14] 之间都是可能的。

所以通常端口通讯中必须具有判断数据长度的附加信息:
要么在数据头指明数据长度,要么在数据末尾加分隔符(该分隔符必须不会在数据中出现)。
现在还是人类 2009-04-21
  • 打赏
  • 举报
回复
就弹片机来说,我是这么发送数据给上位机的

SendBufToPort("DRM-RICM0903A",13);
//============================ 发送数据给串口 ============================
void SendToPort(unsigned char Buf)
{
SBUF = Buf;
while(TI==0);
TI=0;
delay(45);
}

//============================ 发送数据给串口 ============================
void SendBufToPort(unsigned char Buf[],unsigned char Num)
{
unsigned char j;
for(j=0;j<Num;j++)
{
SendToPort(Buf[j]);
}
}

但上位机从理论上来说,应该是一个字节一个字节的收到数据,产生事件也应该是是一个字节一个字节的产生一次事件。
但是,OnComm 事件却不是这样,因为 MSComm 是异步通讯的控件,就像 Winsock 控件一样,也就是收到窗口特定的
Windows 消息后才产生事件的。所以当执行你 OnComm 事件的时候,已经经过了很多复杂的过程,经过了很多通讯周期。
当你开始读缓冲区的时候,已经有很多数据在缓冲区中了。所以就不是我们理解的一个字节一个字节的产生一次事件。
至于你的问题,估计也是和这种系统消息有关。具体为什么会这样,估计和速度还有缓存有关。
Tsunami87 2009-04-21
  • 打赏
  • 举报
回复
我还是不明白~~

单片机是每次的到电脑的允许发送信息后,才发送信息给电脑的,每次发送10字节,然后等待电脑的允许发送信息,才继续发生下一个10字节,MSCOMM设置成接收到10字节后才INPUT入数据的.为什么单片机每次都是发10字节,而电脑那边 却不是每次都是10字节呢?甚至发生顺序的不一制?

of123 2009-04-21
  • 打赏
  • 举报
回复
去掉这句:

MSComm1.InBufferCount = 0

因为单片机在你接收前又发送了。
Tiger_Zhao 2009-04-21
  • 打赏
  • 举报
回复
InBufferCount 只表示已收到的数据长度,与应有数据长度没有直接关系。
自己将接收的数据复制到待处理的数组中,满足一定长度后再处理:
Static d(100) as byte
Static Count as long
dim ...

If MSComm1.CommEvent = 2 Then
'count = MSComm1.InBufferCount 不要'
'MSComm1.InputLen = 10 不要'
Buffer = MSComm1.Input
MSComm1.InBufferCount = 0

For i = LBound(Buffer) To UBound(Buffer)
d(count) = Buffer(i)
count = count + 1
Next i

while Count >=10
c = c+1
'处理前10个数据'

'将 d(10) 开始的数据前移到 d(0) 处'
count = count - 10
wend
Tsunami87 2009-04-21
  • 打赏
  • 举报
回复
怎么没人啊~~~~~~~~~~~
zdingyun 2009-04-21
  • 打赏
  • 举报
回复
LZ:你为解决你的问题多次发问贴,据我了解至少有3贴:
1)本贴
2)http://topic.csdn.net/u/20090418/16/1f0953f8-214b-42ee-a3f8-bd8a91676ad9.html
3)http://topic.csdn.net/u/20090417/16/81390c4d-a691-403d-98a5-505b3e6c734e.html
从本贴给出的代码看与其它两贴非常相似,但从未看到你准确叙述通信协议.对于你网络发送数据部分从代码中暂时注释,仍较以难理解你的代码.我记得本论坛有高手说过,有一个好的通信协议可以事半功倍.否则是事倍功半.
数据帧最好有明确的数据帧头和帧尾以及帧字节长度,接收代码可依据帧头和帧尾及帧字节长度判断来进行数据处理。
以下代码在接收每秒10次的固定字节长度的数据(10字节),没有其它事项,InBufferCount在执行MSComm1.Input前后保持稳定,前为10,后为0:
Option Explicit
Dim strData As String
Dim Lreceive As Integer
Dim sum As Integer
Private Sub Form_Load()
MSComm1.InputLen = 0
MSComm1.Settings = "9600,n,8,1"
MSComm1.InputMode = comInputModeBinary
MSComm1.RThreshold = 1
MSComm1.PortOpen = True
End Sub

Private Sub MSComm1_OnComm()
On Error Resume Next
Dim Buffer As Variant
Dim i As Integer
Select Case MSComm1.CommEvent
Case 2
sum = sum + 1
Text1 = "OnComm次数" & sum
Lreceive = MSComm1.InBufferCount
Text2 = "Input前缓冲区字节数=" & Lreceive
Buffer = MSComm1.Input
Lreceive = MSComm1.InBufferCount
Text3 = "Input后缓冲区字节数=" & Lreceive
For i = LBound(Buffer) To UBound(Buffer)
strData = strData & Right("0" & Hex(Buffer(i)), 2)
Next i
'Text1 = strData
Text4 = "已接收字节数=" & Len(strData) / 2
Text5 = "接收字节数/OnComm次=" & (Len(strData) / 2) / sum
End Select
End Sub




1,451

社区成员

发帖
与我相关
我的任务
社区描述
VB 控件
社区管理员
  • 控件
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧