c++ - 通过 CDC COM 端口到 Arduino 的 Windows COM 通信

标签 c++ c arduino serial-communication cdc

我刚买了一个 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,但遗憾的是这不是一个选择。

我正在使用 Visual Studio 2015 在 Windows 10 上进行编译。我还使用带有 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);
}

Arduino 上的 Rx LED 疯狂闪烁,但 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 与我使用过的其他微 Controller 如此不同?我将逐一检查并测试它们,直到找出问题所在,因为这仅在我第一次打开和关闭 PuTTY 中的端口后连接时才有效(不方便)。

最佳答案

当您在 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
...

关于c++ - 通过 CDC COM 端口到 Arduino 的 Windows COM 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36913723/

相关文章:

c++ - 允许销毁 std::fstream 是否会关闭相关文件?

c - 如何在 C 中将整数转换为 Unicode 字符串?

c - 这个用于查找写入的最小数字的基本 if 代码有什么问题

windows - Cygwin - 串行端口列在/dev 但 stty 报告无效参数

python - 将浮点型数据从 Arduino 发送到 Python

arduino 上的 C++ vector 占用大量 RAM 空间

c++ - 在类中使用 libuv

c++ - 来自原始数据的 QOpenGLTexture (Qt) (freeimage)

c++ - 为什么指针不能转换为引用?

在MinGW(使用MSYS)中为Windows 10编译GTK+-2.0程序