QSerialPort: readline() niekiedy nie czyta wszystkiego.

QSerialPort: readline() niekiedy nie czyta wszystkiego.
FQ
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 9 lat
  • Postów:59
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:

Kopiuj
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 ?

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
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


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22
FQ
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 9 lat
  • Postów:59
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.

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
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.


edytowany 1x, ostatnio: kq
FQ
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 9 lat
  • Postów:59
0

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

MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
0

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


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
FQ
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 9 lat
  • Postów:59
0

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

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

Kopiuj
   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();
    }
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
1

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


MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
1

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
FQ
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 9 lat
  • Postów:59
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.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)