Приходит разбитый на части пакет по UART (QSerialPort)



  • Всем доброго времени суток, товарищи форумчане :)

    Хочу попросить у вас помощи, проблема вот в чем:

    По СОМ порту приходит достаточно большой пакет, пример:

    FCD>PC: Cg + 1.0 2.000000 1000.000000 200 0.50 0.10 0.00 0.00 10.00 10000.00 0.50 25.00 6B0000032940E628 0 10 0 0.0
    

    Записывается пакет в обычную QString переменную. Но записывается таким образом, что пакет разбитый на 3 части. На склеивать.
    Я склеил:

    while(serialForReading->waitForReadyRead(100))
          lastPacketFromPort += serialForReading->readAll();
    

    Но у меня параллельно работает таймер и после получения пакета нужно отключиться от порта.

    Так вот: когда приходит пакет, я останавливаю таймер и отключаюсь от порта, но когда происходит отключение - происходит вылет.

    Что я не так делаю? Почему вылет? Как лечить?

    Буду премного благодарен :)



  • @razorqhex said in Приходит разбитый на части пакет по UART (QSerialPort):

    Так вот: когда приходит пакет, я останавливаю таймер и отключаюсь от порта, но когда происходит отключение - происходит вылет.

    Вылет это вообще что?

    Записывается пакет в обычную QString переменную. Но записывается таким образом, что пакет разбитый на 3 части.

    Что это значит? В пакете "дырки"?
    UART buffer слишком мал для всего пакета?
    Вы уверенны, что Ваш UART device работает без ошибок?



  • @sirop said in Приходит разбитый на части пакет по UART (QSerialPort):

    @razorqhex said in Приходит разбитый на части пакет по UART (QSerialPort):

    Так вот: когда приходит пакет, я останавливаю таймер и отключаюсь от порта, но когда происходит отключение - происходит вылет.

    Вылет это вообще что?

    Записывается пакет в обычную QString переменную. Но записывается таким образом, что пакет разбитый на 3 части.

    Что это значит? В пакете "дырки"?
    UART buffer слишком мал для всего пакета?
    Вы уверенны, что Ваш UART device работает без ошибок?

    Когда я получаю пакет, я должен отключиться от порта, но когда я отключаюсь от порта, то происходит вылет программыю

    Вообще, я получаю вот такой пакет:
    0_1520951427389_forum1.png
    а должен пакет быть такой:
    FCD>PC: Cg + 1.0 2.000000 1000.000000 200 0.50 0.10 0.00 0.00 10.00 10000.00 0.50 25.00 6B0000032940E628 0 10 0 0.0

    Но я написал вот эту процедуру:

    QString focusdrive::getFullPacket()
    {
    	QString lastPacket;
    
    	while(serialForReading->waitForReadyRead(100))
    	{
    		lastPacket += serialForReading->readAll();
    	}
    	return lastPacket;
    }
    

    после чего пакет "склеился", но всё равно, когда идет отключение от порта - программа вылетает.

    И ещё, после это процедуры почему-то твориться такое:
    0_1520951686421_forum2.png

    Эти пустые строки бывают совершенно разного количества. Это не зависит от цифры в

    serialForReading->waitForReadyRead(100)
    


  • а должен пакет быть такой:

    Кому должен? UART ничего никому не должен.

    когда идет отключение от порта - программа вылетает

    Значит кто-то где-то накосячил со своим кодом.

    после чего пакет "склеился",

    Склеивать нужно по-другому:

    bool Foo::m_synchronized = false;
    
    void Foo::onReadyRead()
    {
    	for (;;) {
                const auto bytesAvailable = m_uart->bytesAvaileble();
                if (!m_synchronized) {
                    // Ждем заголовок
                    if (bytesAvailable < 4) // меньше чем 'FCD>'
                        return;
                    const auto head = m_uart->peek(4);
                    if (head != "FCD>") {
                        m_uard->read(1); // избавляемся от первого байта в буфере
                        continue;
                    } else {
                        m_synchronized = true;
                    }
                } else {
                     // Ждем хвост
                     const auto probe = m_uart->peek(bytesAvailable);
                     const auto tailIndex = probe.indexOf("\r");
                     if (tailIndex == -1)
                         return; // Еще хвост не пришел.
                     // Теперь у нас в буфере есть целый пакет, читаем его
                     const auto frame = m_uart->read(tailIndex + 2); // Как то так
                     // Что-то делаем с пакетом..
                     emit frameReceived(frame);
                     m_synchronized = false;
                }
            }
    }
    

    По желанию сюда можно еще и добавить сброс QTimer, который выполняет ф-ции вотчдога. Например, при каждом readyRead() таймер должен сбрасываться, но если он сработал, значит пакет битый и мы что-то недополучили и пр, зависит от фантазии.



  • @kuzulis а чем плоха эта функция?

    QString focusdrive::getFullPacket()
    {
    	QString lastPacket;
    
    	while(serialForReading->waitForReadyRead(100))
    	{
    		lastPacket += serialForReading->readAll();
    	}
    	return lastPacket;
    }
    

    Выжидаешь время, пока пакет полностью не придет, а дальше делаешь с ним всё что угодно



  • Тем, что использовать блокирующие ф-ции нужно в отдельном потоке, и без сигналов/слотов. И смысл твоего какого то там таймера теряется, т.к. блокирующие операции будут блокировать евент луп. В итоге как и что у тебя работает - хз. И потом не надо говорить, что "ой, у меня приложение падает, помогите". Кроме того readAll() возвращает не строку, а байтовый массив.. почувствуй разницу.



  • @kuzulis, спасибо. Всё отработало отлично.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.