Инициализация связи через последовательный порт

В то время мы пытаемся создать интерфейс для последовательной связи, чтобы иметь возможность общаться с микропроцессором.

На самом деле - все работает нормально. Почти! Чтобы иметь возможность общаться с нашим контроллером, нам нужно синхронизироваться с ним. Для этого мы пишем строку: "?0{SY}13!", и контроллер должен ответить "!0{SY}F5?", чтобы принять запрос на синхронизацию. Для этого мы используем функцию writeData (которая работает — мы знаем это, используя echo), а после этого мы используем readData для чтения ответа. Проблема в том, что он почему-то ничего не читает. Хотя он возвращает 1 в случае успеха, он постоянно читает символы " " (ничего).

Теперь начинается странная часть - если мы используем внешнюю терминальную программу для инициализации порта (например, putty), а затем закрываем программу, то все работает нормально. Он принимает запрос на синхронизацию, отвечает (и мы можем его прочитать), а дальше мы можем делать все, что хотим. Но если мы не используем внешнюю программу для инициализации порта, это не сработает.

Конструктор для инициализации интерфейса выглядит так:

SerialIF::SerialIF(int baud, int byteSize, int stopBits, char* parity, int debug)
{
    string coutport = getPort();    
    wstring wideport;               
    debug_ = debug;                 //Debuglevel

    sync = false;                   //sync starts with false

    error = false;                  //Error false as beginnging

    //this is just for converting to the right type
    for (int i = 0; i < coutport.length(); i++)
    {
        wideport += wchar_t(coutport[i]);  
    }
    const wchar_t* port = wideport.c_str();

    SerialIF::hserial = CreateFile(port,
        GENERIC_READ | GENERIC_WRITE,       
        0,
        0,
        OPEN_EXISTING,                      
        FILE_ATTRIBUTE_NORMAL,              
        0);
    if (hserial == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            if (debug_ != LOW)
            {
                cout << "[-] Port " << coutport << "doesn't exist." << endl;  
            }
        }

        if (debug_ != LOW)
        {
            cout << "[-] Handle error - is there another terminal active?" << endl;
        }
        error = true;
    }

    DCB dcbParms = { 0 };
    dcbParms.DCBlength = sizeof(dcbParms);

    if (!GetCommState(hserial, &dcbParms))
    {
        if (debug_ != LOW)
        {
            cout << "[-] Couldn't get status from port " << coutport << endl;
        }
        error = true;  
    }

    if (!error)
    {
        setBaud(dcbParms, baud);
        setParity(dcbParms, parity);
        setByteSize(dcbParms, byteSize);
        setStopbits(dcbParms, stopBits);

        if (debug_ == HIGH)
        {
            cout << "[+] Serial port " << coutport << " has been activated. \nBaud-rate: " << baud << "\nParity: "
                << parity << "\nStop bits: " << stopBits << endl;
        }
    }
    else if (debug_ != LOW)
    {
        cout << "[-] Port not initialized" << endl;
    }
}

Это должно работать - я действительно не знаю, почему это не должно. Он не возвращает ошибок, за последние пару дней я перепробовал МНОГО ошибок, пробовал тайм-ауты, пробовал другие способы его создания, но все сводится к одной и той же проблеме.

Почему это не инициализирует порт?

РЕДАКТИРОВАТЬ:

Вывод при попытке синхронизации: Не могу публиковать картинки из-за отсутствия репутации. хотя выводит так:

[+] Активирован последовательный порт COM1. Скорость передачи: 9600 Четность: НЕТ Стоповые биты: 1

[+] -> ?0{SY}13! пишется в порт. ((И здесь он переходит в бесконечный цикл, читая ""))

РЕДАКТИРОВАТЬ: код для чтения:

const int bytesToRead = 1;              //I byte pr læsning
char buffer[bytesToRead + 1] = { 0 };   //Bufferen til data
DWORD dwBytesRead = 0;                  //Antal bytes læst
string store;                           //Store - den vi gemmer den samlede streng i
bool end = false;                       //Kontrolvariabel til whileloop.

while (end == false)                    
{
    if (ReadFile(hserial, buffer, bytesToRead, &dwBytesRead, NULL)) 
    /*Readfile læser fra interfacet vha. hserial som vi oprettede i constructoren*/
    {
        if (buffer[0] == '?')           //Da protokollen slutter en modtaget streng med "?", sætter vi end til true 
        {                               //Hvis denne læses.     
            end = true;     
        }
        store += buffer[0];
    }
    else
    {
        if (debug_ != LOW)
        {
            cout << "[-] Read fail" << endl;    //Hvis readfile returnerer false, så er der sket en fejl. 
        }
        end = true;
    }
}

if (debug_ == HIGH)
{
    cout << "[+] Recieved: " << store << endl;  //I forbindelse med debug, er det muligt at få udsrkevet det man fik ind.
}

recentIn = store;                               //RecentIN brugES i andre funktioner                
if (verify())                                   //Som f.eks. her, hvor vi verificerer dataen
{
    if (debug_ == HIGH)
    {
        cout << "[+] Verification success!" << endl;
    }
    return convertRecData(store);
}
else
{
    if (debug_ != LOW)
    {
        cout << "[-] Verification failed." << endl;
    }

    vector <string> null;   //Returnerer en string uden data i, hvis der er sket en fejl.
    return null;
}

person Benjamin Larsen    schedule 11.12.2014    source источник
comment
Что выводится при инициализации порта? Как и в , строкой [+] Serial Port....   -  person Greycon    schedule 11.12.2014
comment
Вы можете предоставить код readData()?   -  person alexm    schedule 11.12.2014
comment
@Greycon - я отредактировал исходный пост, включив вывод.   -  person Benjamin Larsen    schedule 11.12.2014
comment
@alexm Я отредактировал сообщение.   -  person Benjamin Larsen    schedule 11.12.2014
comment
Вы полагаетесь на доброту незнакомцев, которые инициализируют DCB для вас. Настройка рукопожатия никогда не бывает второстепенной деталью. Легко отлаживать, просто взглянув на DCB, возвращаемый GetCommState() кстати.   -  person Hans Passant    schedule 11.12.2014
comment
@HansPassant Я понимаю, что ты имеешь в виду. Спасибо, что заметили.   -  person Benjamin Larsen    schedule 11.12.2014
comment
Что ж, метод setHandshake() явно отсутствует. Это соответствует жалобе.   -  person Hans Passant    schedule 11.12.2014
comment
@HansPassant Я попытался отредактировать код `dcbParms.BaudRate = 9600; dcbParms.Parity = NOPARITY; dcbParms.StopBits = 1; SetCommState(hserial, &dcbParms);`, хотя это не повлияло на программу. Стандартные значения для остальных должны быть в порядке. '   -  person Benjamin Larsen    schedule 11.12.2014
comment
Прочтите этот пост, чтобы узнать, что означает рукопожатие.   -  person Hans Passant    schedule 11.12.2014
comment
У меня была та же проблема, хотя я звонил SetCommState. Ссылка, размещенная Хансом Пассантом, помогла мне увидеть проблему. В моем случае это был DtrControl. Большое спасибо !!!   -  person BaldDude    schedule 14.11.2018


Ответы (3)


Вы никогда не звоните SetCommState.

Я не уверен, откуда берутся ваши функции setBaud,setParity и т. д., но я не понимаю, как они могут на самом деле изменить последовательный порт, поскольку у них нет доступа к дескриптору устройства связи.

person Roddy    schedule 11.12.2014
comment
Я вижу, что вы имеете в виду. Только функция GetCommState их получает. Использование SetBaud и т. д.: dcbParms.BaudRate = CBR_110. Я попробую использовать SetCommState. - person Benjamin Larsen; 11.12.2014
comment
..Хотя это имело тот же эффект, используя SetCommState после передачи данных в структуру dcb :-( - person Benjamin Larsen; 11.12.2014
comment
@BenjaminLarsen Вы сможете проверить правильность настройки порта, введя MODE COMn: в командную строку. Или просто вызовите GetCommState во второй раз (в другой DCB) и сравните их. Кроме того, если ваш код работает после запуска PUTTY, сравните DCB, который вы получите после этого, с тем, что после запуска вашей установки. - person Roddy; 12.12.2014
comment
Да, и еще одна вещь: поле StopBits в DCB очень неинтуитивно (0 = 1 стоповый бит, 1 = 1,5 стоповых бита, 2 = 2). Вы должны использовать dcbParms.StopBits = ONESTOPBIT; - person Roddy; 12.12.2014

ReadFile() может вернуть успех, даже если считаны нулевые байты. Используйте dwBytesRead, чтобы найти фактическое количество полученных символов.

while (ReadFile(hserial, buffer, 1, &dwBytesRead, NULL)) 
{
    if (dwBytesRead != 0)
    {
       store += buffer[0];

       if (buffer[0] == '?')  
       {                               
           end = true;     
           break;
       }
    }
}
person alexm    schedule 11.12.2014
comment
Да, я знаю об этом. Я попытался удалить все в буфере. Все пусто. Проблема, вероятно, заключается в конструкторе - просто не могу заставить его работать. - person Benjamin Larsen; 11.12.2014
comment
@BenjaminLarsen Значит, dwBytesRead не равен нулю, верно? - person alexm; 11.12.2014

Была аналогичная проблема между ПК и клоном arduino nano, включая CH340. Этот пост был единственным, который очень хорошо описывает мою проблему. Я решил это, отключив управление потоком DTR (терминал данных готов) и RTS (запрос на отправку), которые обычно активируются после (пере) запуска ПК или подключения Arduino. Я нашел описание этих параметров в документации DCB

Я знаю, что этот пост очень старый, но, возможно, я смогу помочь кому-то еще с этой идеей/решением.

person DGO    schedule 07.06.2020
comment
Ах!! Это наверное и моя проблема! Спасибо! stackoverflow.com/questions/64929987/ - person Jimmy Westberg; 27.11.2020