通过 CDC COM 端口与 Arduino 进行 Windows COM 通信
Posted
技术标签:
【中文标题】通过 CDC COM 端口与 Arduino 进行 Windows COM 通信【英文标题】:Windows COM Communication via CDC COM Port to Arduino 【发布时间】:2016-04-28 11:46:57 【问题描述】:我刚刚购买了一台 SparkFun Pro Micro (https://www.sparkfun.com/products/12640),并尝试在 Windows 10 上使用 ReadFile 和 WriteFile 与其通信。
我已经用 Stellaris、Tiva、Arduino Mega 甚至 Arduino Leonardo 测试并运行了我的代码,几乎没有问题(它有效)。但是,我无法使用微型 USB 电缆和我自己的自定义程序从 Pro Micro 发送任何数据或在我的计算机上接收数据。我可以使用 Arduino 串行监视器来发送和接收数据就好了。我也可以使用 PuTTY 终端。 Arduino IDE 和 PuTTY 中的波特率似乎对使用 Pro Micro 发送/接收数据的能力没有影响。
我希望能够使用我自己的程序发送和接收数据,因为我将它用作数据记录、后处理和实时图形/显示的服务器。如果这个项目不需要更小的硬件包,我会使用 Arduino Mega,但遗憾的是,这不是一个选择。
我在 Windows 10 上使用 Visual Studio 2015 进行编译。我还在使用带有 SparkFuns 插件/驱动程序的官方 Arduino IDE v1.6.7(更新到 1.6.8 时出现同样的问题)。
这是我连接 COM 端口的代码,我尝试了各种波特率以及 BAUD_XXXX 宏:
*port = CreateFile(COM, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); //CreateFile(TEXT("COM8:"), ...
if (*port == INVALID_HANDLE_VALUE)
printf("Invalid handle\n");
return(1);
/// COM Port Configuration
portDCB.DCBlength = sizeof(DCB); ///< Initialize the DCBlength member
GetCommState(*port, &portDCB); ///< Get the default port setting information.
/// Change the DCB structure settings
portDCB.BaudRate = 115200; ///< Current baud
portDCB.fBinary = TRUE; ///< Binary mode; no EOF check
portDCB.fParity = FALSE; ///< Disable parity checking
portDCB.fOutxCtsFlow = FALSE; ///< No CTS output flow control
portDCB.fOutxDsrFlow = FALSE; ///< No DSR output flow control
portDCB.fDtrControl = DTR_CONTROL_DISABLE; ///< Disable DTR flow control type
portDCB.fDsrSensitivity = FALSE; ///< DSR sensitivity
portDCB.fTXContinueOnXoff = TRUE; ///< XOFF continues Tx
portDCB.fOutX = FALSE; ///< No XON/XOFF out flow control
portDCB.fInX = FALSE; ///< No XON/XOFF in flow control
portDCB.fErrorChar = FALSE; ///< Disable error replacement
portDCB.fNull = FALSE; ///< Disable null stripping
portDCB.fRtsControl = RTS_CONTROL_DISABLE; ///< Disable RTS flow control
portDCB.fAbortOnError = FALSE; ///< Do not abort reads/writes on error
portDCB.ByteSize = 8; ///< Number of bits/byte, 4-8
portDCB.Parity = NOPARITY; ///< 0-4 = no, odd, even, mark, space
portDCB.StopBits = ONESTOPBIT; ///< 0, 1, 2 = 1, 1.5, 2
if (!SetCommState(*port, &portDCB))
printf("Error Configuring COM Port\n");
return(1);
GetCommTimeouts(*port, &comTimeOut);
comTimeOut.ReadIntervalTimeout = 20;
comTimeOut.ReadTotalTimeoutMultiplier = 10;
comTimeOut.ReadTotalTimeoutConstant = 100;
comTimeOut.WriteTotalTimeoutMultiplier = 10;
comTimeOut.WriteTotalTimeoutConstant = 100;
SetCommTimeouts(*port, &comTimeOut);
我的读写函数:
char inChar(HANDLE port)
char output = 0;
DWORD noOfBytesRead = 0;
int retval = ReadFile(port, &output, 1, &noOfBytesRead, NULL);
if (retval == 0)
return (0);
return(output);
void outChar(HANDLE port, char output)
DWORD bytesTransmitted = 0;
char buffer[] = output, 0 ;
WriteFile(port, buffer, 1, &bytesTransmitted, NULL);
我有这个来测试 PC 上的通信:
while (1)
outChar(portHandle, 'b');
inchar = inChar(portHandle);
printf("%c", inchar);
在 Arduino 上:
void setup()Serial.begin(115200);
void loop()
Serial.read();
Serial.println('a');
delay(10);
Rx LED 在 Arduino 上疯狂地闪烁,但 Tx LED 什么也没做,这表明数据只有一种方式。我已经完成了其他测试,我发现 Arduino 正在读取正确的信息(如果输入字符是特定字符,则通过闪烁 LED 进行测试)但它不会向我的程序发送任何内容(不使用 Arduino 时的 PC 端IDE 或 PuTTY)。
在 PuTTY 中,无论 Arduinos Serial.begin() 如何,我都能够以任何波特率启动 COM 通信。 8 个数据位,1 个停止位,无奇偶校验,无流控,和我在 Visual Studio 中的设置一样。
编辑: 我想如果我不自己配置它,我只会捎带 PuTTy 留下的 COM 配置,所以我修改了我的代码并删除了所有多余的:
/// COM Port Configuration
portDCB.DCBlength = sizeof(DCB); ///< Initialize the DCBlength member
GetCommState(*port, &portDCB); ///< Get the default port setting information.
/// Change the DCB structure settings
portDCB.BaudRate = 115200; ///< Current baud
portDCB.ByteSize = 8; ///< Number of bits/byte, 4-8
portDCB.Parity = NOPARITY; ///< 0-4 = no, odd, even, mark, space
portDCB.StopBits = ONESTOPBIT; ///< 0, 1, 2 = 1, 1.5, 2
/*
portDCB.fBinary = TRUE; ///< Binary mode; no EOF check
portDCB.fParity = FALSE; ///< Disable parity checking
portDCB.fOutxCtsFlow = FALSE; ///< No CTS output flow control
portDCB.fOutxDsrFlow = FALSE; ///< No DSR output flow control
portDCB.fDtrControl = DTR_CONTROL_DISABLE; ///< Disable DTR flow control type
portDCB.fDsrSensitivity = FALSE; ///< DSR sensitivity
portDCB.fTXContinueOnXoff = TRUE; ///< XOFF continues Tx
portDCB.fOutX = FALSE; ///< No XON/XOFF out flow control
portDCB.fInX = FALSE; ///< No XON/XOFF in flow control
portDCB.fErrorChar = FALSE; ///< Disable error replacement
portDCB.fNull = FALSE; ///< Disable null stripping
portDCB.fRtsControl = RTS_CONTROL_DISABLE; ///< Disable RTS flow control
portDCB.fAbortOnError = FALSE; ///< Do not abort reads/writes on error
*/
注释代码可以正常工作,但为什么呢?是什么让这款 Pro Micro 与我使用的其他微控制器如此不同?我将逐一测试它们,直到找出哪个负责,因为这只有在我第一次在 PuTTY 中打开和关闭端口后才有效(不方便)。
【问题讨论】:
【参考方案1】:当您在 Windows DCB 结构中禁用 RTS 控制时,SparkFun Pro Micro 不喜欢它。
问题已通过以下方式解决:
portDCB.fRtsControl = RTS_CONTROL_ENABLE; //was RTS_CONTROL_DISABLE
portDCB.fOutxCtsFlow = TRUE; //was FALSE
像往常一样,忽略数据表中的重要信息是一个错误,我花了几个小时阅读寄存器信息,试图确认我出错的地方或原因,答案很简单,正如所见的是 USART 设备的功能列表在数据表中:
USART:
...
• Flow control CTS/RTS signals hardware management
...
【讨论】:
【参考方案2】:char inChar(HANDLE port)
char output = 0;
DWORD noOfBytesRead = 0;
int retval = ReadFile(port, &output, 1, &noOfBytesRead, NULL);
if (retval == NULL)
return (NULL);
return(output);
这是不正确的,因为您将 retval(它是 int)与 NULL 进行比较,并且您的函数返回 NULL 作为 char 函数的返回值。尽管我不认为这会导致报告的问题,但应该对其进行更改。
查看接受的答案here。我建议您从 PC 端的一个工作示例开始,然后根据您的需要减少它。
【讨论】:
NULL 被定义为 0。我已经将大部分 NULL 调用替换为 0 以使其更清晰。为花时间浏览我的代码干杯。 这很好,但不常见,因为 NULL 的预期用途是与指针一起使用。查看提供的链接,似乎端口超时的显式设置可能很棘手...... 是的,我在 99% 的时间里都在尝试使用带指针的 NULL,你发现我在做我不应该做的事情。我发现了问题,我觉得自己像个白痴,但希望如果他们尝试类似的事情,它会对其他人有所帮助。 哎哟。该板使用流量控制。这解释了一切 :-) 好消息是这个帖子将来可能会对某人有所帮助。以上是关于通过 CDC COM 端口与 Arduino 进行 Windows COM 通信的主要内容,如果未能解决你的问题,请参考以下文章