串行端口输入缓冲器的Stange行为 [英] Stange Behavior of the Serial Port Input Buffer

查看:176
本文介绍了串行端口输入缓冲器的Stange行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用w/usbser.sys虚拟串行端口作为驱动程序;我得到了一些奇怪的缓冲区行为.由于性能原因,我使用Win32调用(CreateFile,ReadFile等)而不是.NET中的SerialPort类.

Using a virtual serial port w/usbser.sys as driver; I get some strange behavior of the buffers. I use Win32 calls (CreateFile, ReadFile, etc) rather than the SerialPort class in .NET for performance reasons.

打开COM端口后,我使用SetupComm(hFile,dwInQueue,dwOutQueue)将输入缓冲区设置为32768. 4096、8192等

After opening the COM port, I use SetupComm(hFile, dwInQueue, dwOutQueue) to set the input buffer to 32768. I've tried with other sizes, eg. 4096, 8192, etc.

然后,我用GetCommProperties(hFile,lpCommProp)读回缓冲区大小,并读COMMPROP.dwCurrentRxQueue以检查是否已设置大小.但是无论我尝试设置的大小如何, dwCurrentRxQueue始终返回16384

Then I read the buffer size back with GetCommProperties(hFile, lpCommProp) and read the COMMPROP.dwCurrentRxQueue to check if the size has been set. But whatever size I try to set, the dwCurrentRxQueue always returns 16384!

为什么?

我有一个System.Timers.Timer,它每10毫秒启动一次,并调用ReadFile(...),然后对字节进行处理.当计时器挂起时(例如,通过调用Thread.Sleep 5秒钟),虚拟串行端口的缓冲区将在逻辑上填满.睡眠后,我使用ClearCommError(...)检查缓冲区中的字节数,读取COMSTAT的cbInqueue.

I've got a System.Timers.Timer that kicks in every 10ms and calls ReadFile(...) and then does something with the bytes. When the timer is suspended (eg. by calling Thread.Sleep for 5 secs) the buffer of the virtual serial port logically fills up. After sleeping, I check the number of bytes in the buffer using ClearCommError(...), reading cbInqueue of COMSTAT.

由于dwCurrentRxQueue显然为16384,因此您希望在5秒钟的睡眠后将缓冲区中的16K数据打包.但是,即使在睡眠10-20-30秒后,缓冲区也永远不会包含超过〜12K 的数据!

Since the dwCurrentRxQueue apparently is 16384, you'd expect the buffer to be packed with 16K of data after a 5 sec sleep. But the buffer never contains more than ~12K of data, even after sleeping for 10-20-30 secs!

为什么?

以下是代码摘录:

_handle = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);

SetupComm(_handle, 32768, 32768)

// ... other calls (SetCommState, SetCommConfig, SetCommTimeouts)

var commprop = new COMMPROP();

GetCommProperties(_handle, ref commprop)

// commprop.dwCurrentRxQueue always returns 16384

System.Threading.Thread.Sleep(5000);

COMSTAT comstat;
uint    errors;

ClearCommError(_handle, out errors, out comstat);

// comstat.cbInQueue never contains more than ~12 KBytes :s

方法和结构签名已从pinvoke.net获取

推荐答案

使用w/usbser.sys虚拟串行端口作为驱动程序

Using a virtual serial port w/usbser.sys as driver

USB仿真器驱动程序通常不会花很多力气来完美地模拟串行端口.诸如波特率,奇偶校验和握手之类的东西在USB上根本没有意义,因此完全被伪造了.显然,这也不会模拟缓冲区大小.

USB emulator drivers generally don't make much effort to simulate a serial port perfectly. Things like baudrate, parity and handshaking just don't make sense on USB so are completely faked out. This one clearly doesn't emulate a buffer size either.

不清楚您为什么担心它,但这不是问题.您必须始终注意ReadFile()返回的字节数(lpNumberOfBytesRead),它偶然等于nNumberOfBytesToRead.因此,只需反复调用ReadFile()即可填充您自己的缓冲区.顺便说一句,请使用.NET SerialPort类来避免打针.

It isn't clear why you worry about it but it is a non-issue. You must always pay attention to the number of bytes (lpNumberOfBytesRead) that ReadFile() returns, it is only ever equal to nNumberOfBytesToRead by accident. So just call ReadFile() repeatedly to fill your own buffer. Btw, use the .NET SerialPort class to avoid the pinvoke.

这篇关于串行端口输入缓冲器的Stange行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆