Коммуникация Windows COM через CDC COM-порт в Arduino

Я только что купил SparkFun Pro Micro (https://www.sparkfun.com/products/12640) и пытаюсь связаться с ним с помощью ReadFile и WriteFile в Windows 10.

Я протестировал и запустил свой код на Stellaris, Tiva, Arduino Mega и даже Arduino Leonardo практически без проблем (это работало). Однако я не смог отправить какие-либо данные из Pro Micro или получить данные на моем компьютере с помощью кабеля micro USB и моей собственной программы. Я могу использовать серийный монитор Arduino для отправки и получения данных просто отлично. Я также могу использовать терминал PuTTY. Скорость передачи данных в Arduino IDE и PuTTY, похоже, не влияет на возможность отправки / получения данных с помощью Pro Micro.

Я хочу иметь возможность отправлять и получать данные, используя мою собственную программу, поскольку я использую ее в качестве сервера для регистрации данных, последующей обработки и отображения / отображения в реальном времени. Если бы этот проект не требовал меньшего аппаратного пакета, я бы использовал Arduino Mega, но это, к сожалению, не вариант.

Я компилирую на Windows 10, используя Visual Studio 2015. Я также использую официальную среду разработки Arduino с надстройкой / драйверами 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);
}

На Ардуино:

void setup(){Serial.begin(115200);}
void loop(){
Serial.read();
Serial.println('a');
delay(10);
}

Индикатор Rx мигает, как сумасшедший, на Arduino, но индикатор Tx ничего не делает, показывая, что данные передаются только в одном направлении. Я провел другие тесты и обнаружил, что Arduino читает правильную информацию (проверяется миганием светодиода, если входной символ является конкретным символом), но он просто не отправляет что-либо в мою программу (на стороне ПК, когда Arduino не используется IDE или замазка).

В PuTTY я смог инициировать COM-связь с любой скоростью передачи данных, независимо от Arduinos Serial.begin (). 8 бит данных, 1 стоповый бит, без контроля четности, без контроля потока, так же, как моя установка в Visual Studio.

Редактировать:
Я подумал, что если бы я не настроил его сам, я бы просто воспользовался конфигурацией COM, оставшейся от PuTTy, поэтому я изменил свой код и удалил все лишнее:

/// 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

Решение

SparkFun Pro Micro не нравится, когда вы отключаете управление RTS в Windows DCB Structure.

Проблема решена с помощью:

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. Хотя я не верю, что это вызывает проблему, о которой сообщают, это должно быть изменено.

Посмотрите на принятый ответ Вот. Я бы посоветовал вам начать с рабочего примера на стороне ПК, а затем сократить его до ваших потребностей.

0