为什么COM口一次只能接收8个字符?
--------------------编程问答--------------------
MSComm1.InputLen = 0 '为 0 时,使用 Input 将使 MSComm 控件读取接收缓冲区中全部的内容。
http://topic.csdn.net/u/20090926/13/af35d2ff-be38-445e-b306-8481183347d3.html --------------------编程问答-------------------- 还有就是你如果发送速度太快了,接收反应不过来,MsComm1_OnComm() 事件就会有粘带,就是说一个事件里就有几个字符了,试着做适当的延时试试。
--------------------编程问答-------------------- 还有就是你如果发送速度太快了,接收反应不过来,MsComm1_OnComm() 事件就会有粘带,就是说一个事件里就有几个字符了,试着做适当的延时试试。
--------------------编程问答-------------------- http://download.csdn.net/source/1262066
你可以在Input语句钱加一个延迟,等待片刻,等数据全部接收过来。 --------------------编程问答-------------------- LZ:请看关于MSCOMM孔件的讨论,虽然有些争论,但对你有帮助. --------------------编程问答-------------------- 这是一般关于串口通信的书籍,说的很详细,搞懂了它,串口通信不是问题。
http://download.csdn.net/source/1498637
http://download.csdn.net/source/1498644 --------------------编程问答-------------------- 回复6楼,你说的资料,我早下载了,是不错,不过并没有说到为什么不能接收超过8个字符的问题,如果有,我也不会上来了,
回复3楼,你讲的我觉得有点道理,不过我还是有些不明白,你的意思是说当刚接收到一个字符时候,On_COmm事件触发,等到去接收的时候,已经有好些字符了,然后一下子就取了好几个字符,但我做了实验,我把波特率从9600改到2400,还是一次只能接收到8个字符,按照书上所说,我认为
TEXT.TEXT=MSComm1.input 始终是一个字符,因为只要来一个字符就会触发,然后读取数据,等第2个字符来时,TEXT.TEXT又变为当前的字符了,即使等读数据的时候,因为要执行代码有些延迟,里面已经接收到好几个字符了,但是为什么偏偏正好是8?(我在网上看到过好多人都有这情况),而且我把波特率变成2400,也就是以前的1/4,还是8个字符,理论上说应该为是2个字符了,因为执行代码时间是一样的,但波特率变了,那等我执行代码 TEXT.TEXT=MSComm1.input 时,串口缓冲区的字符数应该为以前的1/4,也就是2个字符, --------------------编程问答--------------------
可能是硬件或驱动的问题吧,比如RS232芯片里面有个8字节的寄存器用来临时保存收到的数据,如果传送的数据量超过8字节,当那8字节的寄存器都存满了以后才会产生中断通知Windows去吧里面的数据一次性的读取到内存(InputBuffer)里,然后再清空寄存器继续接收下一批数据,从表面上看起来像是一次性收到8个字符,其实实际上是1个Bit 1个Bit接收的,这种方式可以有效的减少中断的次数提高系统的工作效率。
虽然这只是我个人的猜测,但是这个问题不重要,只要发出的数据都能被正确的接收到就可以了,至于中间是怎么个过程其实无所谓,就像是你有100个箱子要按顺序从A地运到B地,你把这个事情交给货运公司以后,至于货运公司怎么个运法那就是他的事了,他可以选择空运、铁路、公路、水路甚至肩扛手挑都行,他可以一次运一个也可以一次运10个甚至一次运100个,只要他能在指定的时间里把那100个箱子在B地按你原来的顺序交给你就可以了。而你每一次通过InputBufferCount查询InputBuffer里的数量大致就相当于你询问货运公司运到了多少,你可以选择等100(Rthreshold=100)个箱子都到了以后让货运公司主动通知你去取,也可以选择每到15(Rthreshold=15)个箱子就让货运公司通知你一声,如果货运公司每次运10个,那么他第一次通知你的时候实际已经运到了20(InputBufferCount=20)个,你可以在货运公司每次通知你的时候就去把已经运到的箱子从货运公司在B地的临时仓库里提回来,也可以选择等100个箱子都到了以后再去提。
你的 Rthreshold=1就相当于当有一个箱子送到的时候就让货运公司通知你,然后你就把所有已经送到的箱子取走(Text2.Text = MSComm1.Input),货运公司一车可以运送8个箱子,那么当第一车送到的时候货运公司就通知你去取了,显然虽然这一车上有8个箱子但是货运公司只会通知你1次而不是8次,如果在第二车到达之前你没有去取,那么第二车到了以后显然货运公司是不会再次通知你的,因为上一次通知你去取的东西你还没取,等你去取的时候直接把所有的10个箱子都给你就行了,没必要再次通知你。如果在第二车到达之前你已经把第一车的箱子都取走了,那么货运公司自然会再次通知你去取,显然你不能因为第二车上只有两个箱子而不承认已经收到了第一车的8个箱子,这也是为什么Text2.Text = MSComm1.Input是错的,而Text2.Text =Text2.Text & MSComm1.Input是对的。 --------------------编程问答--------------------
'定义一个数据缓冲池,这里用Collection对象作缓冲池,你也可以用数组或其他东西
Dim coldata As Collection
Private Sub Form_Load()
'初始化数据缓冲池
Set coldata = New Collection
'初始化并打开串口
MSComm1.CommPort = 1
MSComm1.Settings = "9600, n, 8, 1"
MSComm1.RThreshold = 1 '设置为每收到一个字节数据触发一次Oncomm事件
MSComm1.InputMode = comInputModeBinary
MSComm1.PortOpen = True
End Sub
Private Sub MSComm1_OnComm()
Dim yy As Long
Select Case MSComm1.CommEvent
Case comEvReceive
Dim xx() As Byte
xx = MSComm1.Input
For yy = 0 To UBound(xx) '把串口接收到的所有数据都先保存到数据缓冲池暂时不去处理,因为无法保证数据已经接收完整
coldata.Add xx(yy)
Next yy
End Select
End Sub
'用Timer控件循环对接收到的数据进行处理,如果你会用多线程的话可以另开一个线程来单独处理
Private Sub Timer1_Timer()
Dim xx As Long
For xx = 1 To coldata.Count '遍历所有串口收到的数据
'代码略,按照通讯协议对串口收到的数据进行分析和处理
'处理完成及时把已处理的数据从缓冲池中移除
Next xx
End Sub
这是我处理串口接收数据的代码,大致上相当于我自己盖了个仓库(coldata),不管货运公司收到什么,只要是我的都给我拉到我自己的仓库里放着,然后我定期的去我的仓库里看看(Timer1_Timer),当我的仓库里存储的东西达到某个条件的时候我就把仓库里的东西取出来拿去做进一步的加工。 --------------------编程问答-------------------- "比如RS232芯片里面有个8字节的寄存器用来临时保存收到的数据" 应该是计算机主板上的IO接口芯片 --------------------编程问答-------------------- Text2.Text =Text2.Text & MSComm1.Input
也许可以 --------------------编程问答-------------------- 谢谢三楼的狼,你说得已经很详细了,基本上能解释所出现的问题,但是您说“比如RS232芯片里面有个8字节的寄存器用来临时保存收到的数据”,以前学过232的时候,好像是UART受到了停止位后,就将串行数据转化为并行数据,然后发送中断通知CPU来取数据,好像说232芯片内只有一个8位的数据寄存器,等收到一个字节就通知CPU来取了,不知道是不是以前学习的芯片比较老,现在电脑里面的232芯片有8个字节的数据寄存器吗? --------------------编程问答--------------------
赞同LS的见解,我给LZ提供的链接不知道LZ是否看过?
我在那儿提供的实验证实不同的硬件会有不同的结果,只能说明构成串口的硬件不同或其驱动不同会导致上述现象.各种硬件构成的串口只要符合RS232口标准就行,重要的是如何按照通信协议做好算法,正确实施通信. --------------------编程问答-------------------- 你的VB代码有问题,我已经回答过了
别撤的那么远 --------------------编程问答--------------------
这个我也不确定是不是232芯片的问题,也可能是操作系统的问题或者是主板上的别的芯片的问题,毕竟你的VB程序是运行在操作系统之上的,我只是随便举了个可能的例子而已,而且对于软件开发者来说这个问题也没有必要深究下去。 --------------------编程问答-------------------- 受教了,我也学了不少 --------------------编程问答-------------------- 我也碰到LZ这样的问题,现在就用 text1.text=text1.text & mscomm1.input的方式把全部收下来,然后再对文本框进行处理,用的是扫描枪扫条形码,看看我的资源(参考)http://download.csdn.net/source/1785013,如果没分的话留下邮箱发给你也行 --------------------编程问答-------------------- 这种问题我也遇到过,和LZ一样查了不少资料也问了不少人都没有得到真正的原因和解决方法,没办法我写的通信代码就一次之处理8个字符.增加了不少代码,如果LZ解决了问题,别忘了告诉小弟一声,谢谢! --------------------编程问答--------------------
原因是 PC 代码的运行速度比串口通讯快。当事件触发的时候,接收端还没有收到所有的字符。
--------------------编程问答-------------------- 我也遇到这样的问题,请高手指教! --------------------编程问答-------------------- --------------------编程问答-------------------- 这是前面的设置,请高手帮忙看下问题
Private Sub CommInit()
Call Commsetting(FirstCOM, FirstComSet)
MSComm1.InputMode = 1 ' comInputModeBinary '//以二进制方式读数据
MSComm1.InputLen = 0 '//设置或返回一次从接收缓冲区中读取字节数,0表示一次读取所有数据
MSComm1.InBufferSize = 512 '//设置接收缓冲区512 Byte
MSComm1.InBufferCount = 0
MSComm1.OutBufferSize = 512 '//设置发送缓冲区512 Byte
MSComm1.OutBufferCount = 0
MSComm1.RThreshold = 59 'InputDataLen '//n个字符到接收缓冲区都触发接收事件
MSComm1.SThreshold = 0 'OutputDataLen
End Sub --------------------编程问答--------------------
把你代码中的
MsgBox "通过"
注释掉. --------------------编程问答-------------------- 谢谢你的关心,这是我特意设的,关键是不出现这个通过,我经过多种测试,发现如果接收缓存区512,最多也就能接收8个数据,所以,我不想把缓冲区改得特别大,对于我每次接收的固定59字节,我想了笨方法,就是只要进来6个字节,我就启动,然后在触发事件中加延时,实验结果很好用,我只是想明白VB中究竟是什么问题!我的程序没问题,早就能用了!谢谢你的关心!
补充:VB , 基础类