QSerialPort: readline() niekiedy nie czyta wszystkiego.

0

Witam

Pobieram dane z portu szeregowego za pomocą funkcji readline() po sygnale readyread(), każda nową linie dodaje do buffora QByteArray przy pomocy funkcji append(). Zauważyłem jednak, że często pobieranie danych poprzestaje jeśli, któraś z pobranych linii zakończona jest znakiem (unsigned char) = 10 . Co więcej zdarzyło mi się tak, że pobierałem zawsze 260 bajtów później odsyłałem je do urządzenia lecz ich wartości były zmodyfikowane przeze mnie i kiedyś zapisałem je tak, że bajt 235 kończył się (chyba) 10, wtedy mimo, że urządzenie przesyłało mi z powrotem 260 (sprawdziłem w innym programie) ja dostawałem w programie tylko 235 ze względu (chyba)na znak EOF. Wyczytałem w dokumentacji że:

Data is read until either of the following conditions are met:

The first '\n' character is read.
maxSize - 1 bytes are read.
The end of the device data is detected.

Ktoś może mi powiedzieć jak działa dokładnie ten mechanizm, bo w całej paczce 260 bajtowej zdarzają się znaki EOF, a mimo tego qt czyta dalej. Muszą być jakieś warunki spełnione łącznie ?

2

zdajesz sobie chyba sprawę, że '\n'==10?
Opisałeś problem tak jakbyś tego nie wiedział.
Pokaż cały kod slotu.
Popatrz też na tą odpowiedź: http://4programmers.net/Forum/C_i_C++/238111-qt_i_qserialport_odbieranie_danych_w_osobnym_watku?p=1060600#id1060600

0

Ne mam teraz dostepu do kodu i pisze z telefonu. Tak jak pisalem po sygnale readready() wpadam do slotu ktory jest z nim polaczony i jedyne co robie to dodaje do zdeklarowanego obiektu QBytearray receive nowa linie
receive.append(this->readline())
I to wszystko. Pozniej po jakims timeout odczytuje receive.

1

EOF nie ma wartości z zakresu [0,255], więc nie może znajdować się w treści wiadomości. Natomiast, tak jak @MarekR22 napisał, '\n' to w ASCII 10, a ponieważ Twoje środowisko używa ASCII to readLine odczytuje do tego znaku i kończy działanie - bo linia się skończyła. Masz dwie opcje: albo odpytasz czy bytesAvailable() > 0 po pobraniu linii (i będziesz powtarzał tak długo jak będzie to prawdą), albo użyjesz readAll zamiast readLine.

0

Readall daje ten sam efekt. Sproboje z funkcja bytesavaiable tylko misze to jakos rozsadnie polaczyc.

0

Pokaż kod i opisz jakie dane ci przychodzą: tekstowe linia po linii? binarne? W jakim formacie?

0

Rozwiązałem sprawę, za waszą pomocą, korzystając z funkcji bytesAvailable().

//po sygnale readyRead()
void COM_Configure::SLOT_ReciveData()
{

 if(flagASK)
    {
         //qd "ODBIOR dostepne bajty przed odczytem" << this->bytesAvailable() ;
         receive.append(this->readAll());
         while(this->bytesAvailable() > 0)
         {
            receive.append(this->readAll());
         }
    }

}

Czyli jeśli została odczytana linia to sprawdzam czy jest coś jeszcze w buforze i dodaje dopóki nie będzie pusty. To działa poprawnie.
Teraz z kolei zostaje mi kwestia nadawania znaku '/n'
korzystając z funkcji this->write(data) jeśli data to np:
220 , 48 , 10 , 12 ,13 ,14 , 15
funkcja this->write(data) wysyła jedynie 2 znaki do napotkania 10. Jakieś propozycje jak to przeskoczyć?

@MarekR22
Urządzenie ma mi w odpowiedzi przesłać paczkę 260 bajtów, ostatni bajt to CRC. Dane z tego co widać na pewno nie przychodzą w liniach, więc pewnie binarnie. Wynika z tego, że koniec transmisji polega na wykryciu przez program "The end of the device data is detected." i to by mnie najbardziej interesowało tzn. emisja danego sygnału jeśli to nastąpi. Pytanie czy jest jakaś funkcja, która to wykrywa ? Jeśli skorzystam z this->at.end() w poniższy sposób dostaje ciągle true. A niekiedy powinienem dostać false w szczególności jak 260 bajtów przychodzi pare razy w paczkach po 50, bo to przecież nie koniec nadawania.

   if(flagASK)
    {
         //qd "ODBIOR dostepne bajty przed odczytem" << this->bytesAvailable() ;

         receive.append(this->readAll());
         qd "end przed while" << this->atEnd();

         while(this->bytesAvailable() > 0)
         {
            receive.append(this->readAll());
         }
         qd "end" << this->atEnd();
    }
1

wywołaj writez 2 argumentami: wskaźnik i wielkość danych. Ewentualnie przekaż funkcji QByteArray z odpowiednią zawartością.

0

Też taka myśl mnie naszła: dane + sztywny rozmiar no i znalazła się polecana przeładowana funkcja write :). Wszystko działa, tylko musiałem poprzeżucać troche danymi. Nie mniej dziejuję za wszystkie porady. Temat uważam za rozwiązany.

1 użytkowników online, w tym zalogowanych: 0, gości: 1