QSerialPort i prawidłowe odbieranie danych z portu

0

Chciałbym wiedzieć jak najlepiej odczytywać dane z portu za pomocą QSerialPort, mamy wiele funkcji aby to uczynić:

Którą metodę użyć, aby mieć pewność że niczego po drodzę nie zgubię? Mój program będzie się komunikować przez ten port, wiem na 100% że pojedyncza ramka danych będzie składałą się z 20 bajtów, pierwszy bajt umówiony jest jako '&', ostatni jako '$' a więc przykładowa ramka będzie wyglądać: '&xxxxxxxxxxxxxxxxxx$' i tylko i wyłącznie tego typu ramki będą nadawane, teraz moje pytanie jak najlepiej to zrobić, aby odczytywane dane z portu byłu już Od razu podzielone na te moje ramki? Przy okazji żebym niczego nie gubił.

0

Ja, jak pisałem program do komunikowania się z urządzeniem poprzez RS-232, to używałem metody readAll().

Rozumiem, że program będzie otrzymywał fragmenty danych (np. bajt po bajcie), które razem utworzą tę "ramkę", a nie od razu całość, tak? W takim razie ja bym zrobił tak, że wczytywane dane doklejałbym do tablicy bajtów do czasu, gdy program nie otrzyma tego ostatniego bajtu '$'. Kiedy program otrzyma ten bajt, to wtedy mógłbym już użyć tej tablicy bajtów do swoich celów.

Jeżeli zna ktoś jakiś lepszy pomysł, to chętnie bym się dowiedział.

2

Ponieważ oczekujesz zawsze tej samej ramki to najlepiej zrobić tak:

const int WielkoscRamki = 20;
const char PoczatekRamki = '&';
const char KoniecRamki = '$';

//slot podpięty do sygnału readyRead
void twojaKlasa::onReadyReadRs232() {
    QIODevice *dev = qobject_cast<QIODevice *>(sender());
    while(1) {
        if (dev->bytesAvailable()<WielkoscRamki) 
            return; // nie ma dostępnej pełnej ramki, trzeba czekać na więcej danych
        char data[WielkoscRamki];
        dev->peak(data, WielkoscRamki); // podpatrz dostępne dane
        int i=0;
        for (;i<WielkoscRamki; ++i)
            if (data[i]==PoczatekRamki)
                break; // sprawdź lub szukaj poczatku ramki
        if (i!=0) {
            dev->readData(data, i); // data to ignore
            continue;
        }
        dev->readData(data, WielkoscRamki);
        if (dev[WielkoscRamki-1]==KoniecRamki) {
            przetwarzajRamke(data);
        }
    }
}

Czemu tego kodu jest aż tyle? Po pierwsze dane mogą przychodzić w niezdefiniowanych ilościach, mogą to być pojedyncze bajty lub od razu kilka ramek na raz. Po drugie jeśli pojawią się jakieś błędy w transmisji, to potem trzeba wyłapać początek ramki i ten kod próbuje to zrobić.

0

@MarekR22 bardzo ładny kod, widzę że korzystasz tutaj z lotów, a ja muszę napisać to w osobnym wątku, mam coś takiego:

void SerialPortWorker::run()
{
    char buffChar[FrameSize];
    QByteArray buffer;
    QString    frame;

    while(!quit)
    {
        while(serialPort.bytesAvailable() < FrameSize)
        {
            QThread::usleep(10);
        }
        serialPort.read(buffChar, FrameSize);
        buffer = buffChar;

        qDebug() << buffer;

        while(buffer.size() >= FrameSize)
        {
            for(int i = 0; i <= buffer.size() - FrameSize; i++)
            {
                if(isCorrectFrame(buffer.mid(i, FrameSize)))
                {
                    frame = buffer.mid(i, FrameSize);
                    emit readFrame(frame);
                    buffer = buffer.mid(i + FrameSize);
                    break;
                }
            }
        }

    }
}

 

Lecz to nie działa :( Napisałem prostą aplikację na Ardino która po wciśnięciu 1 przycisku wysyła poprawną "ramkę" a po wciśnięciu drugiego przeciusku wysyła śmieci, kiedy podpatrze wysyłane ramki w wbudowanym terminatorze Android IDE to wszystko jest ok, a w moim programie nie :( Czasami dojdą 5 paczek ok, później nic i kicha.

1

Z moim kodem, stosując mechanizm slotów i sygnałów, nie musisz stosować wątków. Na dodatek jeśli się uprzesz stosować wątki, to będzie to o wiele łatwiejsze.
Tu jest mój opis jak używać wątków w qt: http://4programmers.net/Forum/C_i_C++/210633-qt_creator_-_watki?p=918099#id918099
A tu ten z nowszej dokumentacji: http://qt-project.org/doc/qt-5.0/qtcore/qthread.html#details

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