2016-04-28 15 views
2

Я только что купил SparkFun Pro Micro (https://www.sparkfun.com/products/12640) и пытаю общаться с его помощью ReadFile и WriteFile в ОС Windows 10.Windows, COM Связь через CDC COM порт для Arduino

Я проверил и запустить свой код 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); 
} 

на Arduino:

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

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

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

Edit: Я подумал, что если я не настраивал его сам, я бы просто Спекуляцию от конфигурации 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

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

Проблема решается с:

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

Как обычно, это была ошибка в недооценить важную информацию в техническом описании, я проводил часы чтения с помощью информации регистра пытается подтвердить, где или почему я не заладилось и ответ был прост, как видно список функциональности USART устройства в спецификации:

USART: 
... 
• Flow control CTS/RTS signals hardware management 
... 
0
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 (что целое) в NULL, и ваша функция возвращает NULL в качестве возвращаемого значения функции полукокса. Хотя я не считаю, что это вызвало проблему, ее нужно изменить.

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

+0

NULL определяется как 0. Я заменял большинство моей NULL вызовов с 0, чтобы сделать его более ясным. Приветствую вас, чтобы посмотреть время на мой код. – Jarred

+0

Это нормально, но не обычный, поскольку NULL предназначен для использования с указателями. Посмотрите на предоставленную ссылку, кажется, что явные настройки тайм-аутов порта могут быть сложными ... –

+0

Да, я пытаюсь использовать NULL с указателями в 99% случаев, вы поймали меня, делая что-то, чего я не должен делать. Я нашел проблему, и я чувствую себя идиотом, но, надеюсь, это поможет кому-то другому, если они попробуют что-то подобное. – Jarred