代码之家  ›  专栏  ›  技术社区  ›  Jarred

通过CDC COM端口与Arduino进行Windows COM通信

  •  3
  • Jarred  · 技术社区  · 8 年前

    我刚买了SparkFun Pro Micro( https://www.sparkfun.com/products/12640 )并尝试在Windows 10上使用ReadFile和WriteFile与其通信。

    我已经用Stellaris、Tiva、Arduino Mega,甚至Arduino-Lonardo测试并运行了我的代码,几乎没有问题。但是,我无法使用Micro USB电缆和我自己的自定义程序从Pro Micro发送任何数据或在我的计算机上接收数据。我可以使用Arduino串行监视器发送和接收数据。我也可以使用PuTTY终端。Arduino IDE和PuTTY中的波特率似乎对使用Pro Micro发送/接收数据的能力没有影响。

    我希望能够使用自己的程序发送和接收数据,因为我将其用作数据记录、后处理和实时图形/显示的服务器。如果这个项目不需要更小的硬件包,我会使用Arduino Mega,但遗憾的是,这不是一个选项。

    我正在使用Visual Studio 2015在Windows 10上编译。我还使用官方的Arduino IDE和SparkFuns插件/驱动程序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);
    }
    

    我用这个来测试电脑上的通信:

    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进行测试),但它不会向我的程序发送任何内容(如果不使用ArduinoIDE或PuTTY,则在PC端)。

    在PuTTY中,无论Arduinos Serial.begin()是什么,我都能以任何波特率启动COM通信。8个数据位,1个停止位,无奇偶校验,无流控制,与我在VisualStudio中的设置相同。

    编辑: 我想,如果我不自己配置它,我只会利用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中的端口后才能连接(不方便)。

    2 回复  |  直到 8 年前
        1
  •  2
  •   Jarred    8 年前

    SparkFun Pro Micro不喜欢在Windows DCB结构中禁用RTS控制。

    问题通过以下方式解决:

    portDCB.fRtsControl = RTS_CONTROL_ENABLE; //was RTS_CONTROL_DISABLE
    portDCB.fOutxCtsFlow = TRUE;              //was FALSE
    

    与往常一样,忽略数据表中的重要信息是一个错误,我花了数小时阅读寄存器信息,试图确认我出错的地方或原因,答案很简单,如数据表中USART设备的功能列表所示:

    USART:
    ...
    • Flow control CTS/RTS signals hardware management
    ...
    
        2
  •  0
  •   Community CDub    7 年前
    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端的一个工作示例开始,然后根据您的需要进行缩减。