我通过将通信超时设置为{MAXDWORD,0,0,0,0}
.
经过多年的努力,在这一天,我终于能够使用 Microsoft 的 CDC 类 USB UART 驱动程序(USBSER.SYS,现在内置在 Windows 10 中使其实际可用)使我的串行通信终端足够快。
显然,前面提到的一组值是一个特殊的值,它设置了最小的超时和最小的延迟(至少在 Microsoft 驱动程序中,至少在我看来是这样),并且如果接收中没有新字符,也会导致 ReadFile 立即返回缓冲。
这是我打开端口的代码(Visual C++ 2008,项目字符集从“Unicode”更改为“未设置”以避免端口名的 LPCWSTR 类型转换问题):
static HANDLE port=0;
static COMMTIMEOUTS originalTimeouts;
static bool OpenComPort(char* p,int targetSpeed) { // e.g. OpenComPort ("COM7",115200);
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跟踪。请注意 OUT 事务(输出字节),然后是 IN 事务(输入字节),然后是更多的 OUT 事务(输出字节),所有这些都在 3 毫秒内:
最后,如果您正在阅读本文,您可能有兴趣查看我通过 UART 发送和接收字符的函数:
unsigned char outbuf[16384];
unsigned char inbuf[16384];
unsigned char *inLast = inbuf;
unsigned char *inP = inbuf;
unsigned long bytesWritten;
unsigned long bytesReceived;
// Read character from UART and while doing that, send keypresses to UART.
unsigned char vgetc() {
while (inP >= inLast) { //My input buffer is empty, try to read from UART
while (_kbhit()) { //If keyboard input available, send it to UART
outbuf[0] = _getch(); //Get keyboard character
WriteFile(port,outbuf,1,&bytesWritten,NULL); //send keychar to UART
}
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