在我的情况下,我通过将 comm 超时设置为 {MAXDWORD,0,0,0,0}
来解决了此问题。
多年来,我一直苦于使用 Microsoft 的 CDC 类 USB UART 驱动程序(USBSER.SYS),但在今天,我终于成功地使我的串行通信终端更快,并且该驱动程序现已内置于 Windows 10 中,因此变得实际可用。
显然,上述一组值是一个特殊值,它设置了最小超时时间和最小延迟时间(至少在我看来是这样的,而且也会导致如果接收缓冲区中没有新字符,则 ReadFile 立即返回)。
以下是我的代码(Visual C++ 2008,将项目字符集从“Unicode”更改为“未设置”,以避免 portname 的 LPCWSTR 类型转换问题)来打开端口:
static HANDLE port=0;
static COMMTIMEOUTS originalTimeouts;
static bool OpenComPort(char* p,int targetSpeed) {
char portname[16];
sprintf(portname,"\\\\.\\%s",p);
port=CreateFile(portname,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
if(!port) {
printf("COM port is not valid: %s\n",portname);
return false;
}
if(!GetCommTimeouts(port,&originalTimeouts)) {
printf("Cannot get comm timeouts\n");
return false;
}
COMMTIMEOUTS newTimeouts={MAXDWORD,0,0,0,0};
SetCommTimeouts(port,&newTimeouts);
if(!ComSetParams(port,targetSpeed)) {
SetCommTimeouts(port,&originalTimeouts);
CloseHandle(port);
printf("Failed to set COM parameters\n");
return false;
}
printf("Successfully set COM parameters\n");
return true;
}
static bool ComSetParams(HANDLE port,int baud) {
DCB dcb;
memset(&dcb,0,sizeof(dcb));
dcb.DCBlength=sizeof(dcb);
dcb.BaudRate=baud;
dcb.fBinary=1;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;
dcb.ByteSize=8;
return SetCommState(port,&dcb)!=0;
}
以下是它正常工作时的 USB 跟踪数据。请注意在 3 毫秒内连续发生的 OUT 事务(输出字节)、IN 事务(输入字节)以及更多 OUT 事务(输出字节):
![USB UART packet trace with minimal timeouts](https://istack.dev59.com/QrSSY.webp)
最后,由于您正在阅读此文,可能会对查看我发送和接收 UART 字符的功能感兴趣:
unsigned char outbuf[16384];
unsigned char inbuf[16384];
unsigned char *inLast = inbuf;
unsigned char *inP = inbuf;
unsigned long bytesWritten;
unsigned long bytesReceived;
unsigned char vgetc() {
while (inP >= inLast) {
while (_kbhit()) {
outbuf[0] = _getch();
WriteFile(port,outbuf,1,&bytesWritten,NULL);
}
ReadFile(port,inbuf,1024,&bytesReceived,NULL);
inP = inbuf;
inLast = &inbuf[bytesReceived];
}
return *inP++;
}
大规模的传输在代码中另外处理。
最后,值得一提的是,自从1998年放弃DOS以来,这似乎是我写的第一个快速UART代码。哦,时间过得真快,当你玩得开心时。
这是我找到相关信息的地方:http://www.egmont.com.pl/addi-data/instrukcje/standard_driver.pdf