这个问题折磨我好久了 串口通讯:为什么要发送的字节长度和实际发送的字节长度不相同?

jiju 2003-05-27 11:33:39
加精
在writefile以后
我使用GetOverlappedResult( hcom,&Writebuf, &BytesSent, TRUE ))
但是,即使返回true
有时候BytesSent得到的字节数和我需要发送的字节数也不等,

串口通讯在单独的一个线程里运行,特别在拖动窗体时,这种情况发生特别多。

这该怎么办?

写串口时大概13ms写一次,这个速度会影响吗?
...全文
649 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
AthlonxpX86 2003-06-03
  • 打赏
  • 举报
回复
砍了你们的回复越来越糊涂了,什么轮训方式啊CSerialPort类本身就是事件驱动模式,还有 Sander说的driver的buffer小,所以要加快传送串口速率,这都是什么啊,根本不会出现这样的问题,如果出现了,那这应该算是驱动程序的BUG了,把串口通讯的数据迁移分两部的话,1由writefile到驱动程序,2由驱动程序到物理串口发送出去,那你的意思是说因为writefile的速度太快了并且第2部的速度太慢了,所以造成缓冲区益处,丢是数据是吧,那你说的增加波特率其实和增大timeout其实是一样的,timeout是限制writefile的速度,而且增加timeout应该是更简单,效果更好才是,但楼主试验过,这个不行,所以这里根本不是速度的问题,
jjjtang 2003-06-02
  • 打赏
  • 举报
回复
你的发送的数据中有没有0,不是(asc)0,是/0,
字符串以/0结束,后面的就不发了
Sander 2003-06-02
  • 打赏
  • 举报
回复
我是指地层driver的buffer,
因为轮寻方式?说来听听,为什么不用event驱动
quengzi 2003-06-02
  • 打赏
  • 举报
回复
不好意思,我得NetScape好像有点问题,一连发了4个,才提示我不能连续发贴。getqueuedcompletionstatus是在使用完成端口的时候获取状态的,不用完成端口的方式也可以获取吗?
提到完成端口,为什么你只用重复IO,不再加一个完成端口的方式,不就可以更高效率的进行数据传输。
有的时候我writefile之后,返回0,但是接受端可以接收到发送的数据。你是不是测试一下接受端是否可以接受数据。
jiju 2003-06-02
  • 打赏
  • 举报
回复
AthlonxpX86(一滴水) :鱼和熊掌不能兼得

to: Sander()

你指的底层缓冲buffer 是指硬件缓冲区吗?那不是最大只有16个字节的发送缓冲区?


同时,在没有写完前,不允许再发新数据。
________________________________________
我刚才看了一下msdn 是不是可以用GetQueuedCompletionStatus得到发送了多少个字节?我没有试过,不过这种等待方式和FlushFileBuffers好像也没有什么实质上的区别。
不过发送速度和速率不能变,因为轮寻方式,速度降低了就不管钱了(老板说的)

//本来想结贴了,在等等吧,我的信誉分又减了1分:(
quengzi 2003-06-02
  • 打赏
  • 举报
回复
试一试每次写1个byte,然后多开几个线程处理。
quengzi 2003-06-02
  • 打赏
  • 举报
回复
试一试每次写1个byte,然后多开几个线程处理。
quengzi 2003-06-02
  • 打赏
  • 举报
回复
试一试每次写1个byte,然后多开几个线程处理。
Sander 2003-06-02
  • 打赏
  • 举报
回复
不是这样,我是认为GetOverlappedResult(port->m_hComm,&port->m_ov,&BytesSent,false);
即使返回true,windows可能也并没有真正把字符完全写下去,
----------------------------------------------------------------
呵呵,本来就是这样 呀,GetOverLappedResult(),是在有event时返回是true,
如果把函数最后一个参数设成true,它就一定会等event才返回,返回为true,只是表示
有event ,bytesSent中为写的数量。但并不能表示你希望写的数量。
造成这个的原因是因为你写得太快,一般写的数量是min(地层缓冲buffer,要写的数量),你可以通过提高bandrate,来解决这个问题。同时,在没有写完前,不允许再发新数据。
AthlonxpX86 2003-06-02
  • 打赏
  • 举报
回复
你看看楼主的代码,绝对不是你说的那种问题
jjjtang 2003-06-02
  • 打赏
  • 举报
回复
那是版本不一样的CSerialPort类,
我有两个不同的版本,
其中一个就是只带一个字符串参数的
我只是怀疑他是不是用了这个
AthlonxpX86 2003-06-02
  • 打赏
  • 举报
回复
楼上的,你说的那是字符串的,字符串的长度是从开始到第一个NULL为结束,但是串口发送的是2进制应该没有这个限制,它的发送长度应该由writefile的第2个参数决定,即使你发的是字符串,我的串口程序就能发送NULL
AthlonxpX86 2003-06-01
  • 打赏
  • 举报
回复
恩,我明白你的意思了,你的意思是说WriteChar返回后,数据没有写完,如果是

连续的大量数据发送,那第2次调用WriteChar后因为PurgeComm而使得上次的数据

没有发送玩儿丢失了是吧,确实,我以前都认为只要设置好timeout,

GetOverlappedResult返回后WriteFile一定都执行彻底了,看来这真是一个错误

,但还是不知道引起GetOverlappedResult执行错误的原因(是不是还有发送缓冲

区有数据,但不发送数据了,因为某种错误停下来了)你的方法确实可行,但只

是对GetOverlappedResult执行错误的一种补救方法,你看看MSDN上这段文字



If a thread uses PurgeComm to flush an output buffer, the deleted

characters are not transmitted. To empty the output buffer while

ensuring that the contents are transmitted, call the FlushFileBuffers

function (a synchronous operation). Note, however, that

FlushFileBuffers is subject to flow control but not to write time-outs,

and it will not return until all pending write operations have been

transmitted.

看完之后我觉的可能会有新的问题接踵而来,你这样做可能会违背异步串口编程

的基本思想,而导致类似同步串口编程的错误,假如出现某些问题,比如我刚才

假设的那样(是不是还有发送缓冲区有数据,但不发送数据了,因为某种错误停

下来了),或者是别的什么问题,那FlushFileBuffers将永远不会返回了(

FlushFileBuffers is subject to flow control but not to write time-outs,

and it will not return until all pending write operations have been

transmitted. ),这也要妥善处理,闹不好你的程序就死掉了,诶!串口编程看

来没这么简单
jiju 2003-06-01
  • 打赏
  • 举报
回复
不是这样,我是认为GetOverlappedResult(port->m_hComm,&port->m_ov,&BytesSent,false);
即使返回true,windows可能也并没有真正把字符完全写下去,

port->m_ov.InternalHigh不只你们如何理解
我发现在出现我所提到的情况时port->m_ov.InternalHigh在调用writefie函数以后会变成4(小于我要发送的字节数大小),此时GetOverlappedResult也就只写入这4个字节“BytesSent =4”(这是我在设置断点情况下看到的,可能也不是实际执行情况)
也就是说window并没有完全写入所有的字节,其他字节还留在发送缓冲区中,这时候调用PurgeComm
你没有发送出去的字节就会立即清除。

这就是我调用flushfilebuffers 的想法。
我今天没有条件做实验来看看,不知道是不是和我想的一样。:(




AthlonxpX86 2003-05-29
  • 打赏
  • 举报
回复
你的问题先别结贴,真的解决后,如果好,我就把它整理到精华贴和FAQ,


稀里糊涂的,是我看不懂你的代码,还是我真的想错了,你的PurgeComm是在writefile之前调用的,在发送数据的时候不会有清空缓冲区的操作啊,而且因为你在CSerialPort::WriteChar加了临界区,所以每次发送操作都不会在上一次没有发送完数据的时候掉用PurgeComm,

到底怎么回事??????????
jiju 2003-05-29
  • 打赏
  • 举报
回复
谢谢各位的热心支持,我今天我是试了一天,应该解决(因为程序才运行一天,还不能完全判断),
to:athlonxpX86谢谢你,不过由于代码中有公司的内部通讯协议,所以不能发给你,主要是人的信用问题 :) 。其实如果你对设备高速通讯的话应该会出现这个问题(设备要有返回包)
以下是我今天的一点心得:
我认为是
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);这个函数的错误
这个函数会清空所有的数据,包括未发送出去的。
我结果调用 flushfilebuffers 现在效果很好,即使出现我所提的错误,也能正确写入。

不知各位有什么高见?
qrlvls 2003-05-29
  • 打赏
  • 举报
回复
再说,它的消息方式感觉不是很好用
qrlvls 2003-05-29
  • 打赏
  • 举报
回复
CSerialPort的用了StartMonitorin和StopMonitoring亚通过线程读写,但是在传数据块的时候最好自己扩展一下
qrlvls 2003-05-29
  • 打赏
  • 举报
回复
把通讯做到单独的线程中诫诫,我以前一个单线程的也出现过类似问题,后亚用多线程解决掉了
AthlonxpX86 2003-05-28
  • 打赏
  • 举报
回复
我都没遇到过,能不能把你的代码发给我看看,yds_086@163.com
加载更多回复(10)

2,644

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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