QT i QSerialPort Odbieranie danych w osobnym wątku.

0

Witam.

Potrzebuje odebrać dane z RS232. Danych tych mam 255 bajtów, może i będzie więcej. Postanowiłem dane te odbierać przy użyciu sygnału ReadReady() łącząc go z pewnym slotem w klasie
QObject::connect(serial , SIGNAL(readyRead()) , this , SLOT(SLOT_ReciveData()))
Wszystko działa. To znaczy dane są odebrane kompletnie, ale... dane te są odbierane w pewnych paczkach po 50, 30 , 40 bajtów, w główniej mierze zależy to od baud-u. W każdym razie suma się zgadza. Wniosek jest z tego taki, że sygnał ReadReady() generowany jest kilkukrotnie, myślę, że wynika to z tego, że potrzeba osobnego wątku, aby to obsłużyć i aby zajął się tym do końca bez przerw po jednym sygnale.
Trafiłem już na temat
http://4programmers.net/Forum/C_i_C++/210633-qt_creator_-_watki?p=918099#id918099
i post Marka, dzięki któremu zrozumiałem koncepcje, ale mam problem z przełożeniem jej na kod u siebie.
Mam pewną klasę, która zajmuje się konfiguracją QSerialport do niej też spróbowałem dodać obiekt wątku:

COM_Configure::COM_Configure(QString name , Okno_GL*parent) :name(name) , parent(parent)
thread = new QThread(this);
    serial = new QSerialPort();

    serial->moveToThread(thread);
    serial->setPortName(name);
    serial->setBaudRate(QSerialPort::Baud38400); //this is the samed
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    if(serial->open(QIODevice::ReadWrite))
   {
       qd "otwarty" ;
   }

 QObject::connect(serial , SIGNAL(readyRead()) , this , SLOT(SLOT_ReciveData()), Qt::QueuedConnection);
 thread->start();

Po próbie dostaje błąd
QObject: Cannot create children for a parent that is in a different thread.

edit:

tutaj slot w którym dobieram

oid COM_Configure::SLOT_ReciveData()
{
    
    qd "Odpowiedz z UC " ;

    recive = serial->readAll(); // recive to QBytearray zdekralowana jaki zmienna prywatna w klasie


    qd "odebrano dane. Ilosc danych  " << recive.size() ;
    for(int i = 0 ; i < recive.size() ; i++)
    {
        qd "Bajt" << i << (unsigned char)recive[i];
    }


}

edit 2:

Dokopałem sie do czegoś, ale niezbyt obiecujące stwierdzenie
http://qt-project.org/forums/viewthread/40595

0

0

Problemem jest to, że przenosisz obiekt do wątku, którego właścicielem jest dany obiekt.
Tak jak gdzieś pisałem (chyba w podanym linku, ale nie chce mi się szukać), obiekt przeznaczony do przenoszenia do innego wątku, powinien być napisany tak jakby miłą działać na bieżącym wątku i to właściciel tego obiektu powinien przenosić go do wybranego wątku.

Wszystkie strumienie w Qt są asynchroniczne, więc kombinowanie z wielowątkowością w większości wypadków jest bezcelowe (zysk nie jest warty włożonego wysiłku).

0

Tak jak piszesz. Doczytałem na SO, że nie da się odebrać całej paczki. QT robi to różnie w zależności od OS, baud-u itd, itp. Aby zrobić tak jak ja chce należy skorzystać np z funkcji bytesAvailable() , albo poczekać przy pomocy QTimer określony czas, później wpaść do slotu i odebrać dane, taki urok :)
Dzięki za odpowiedzi. Temat uważam za rozwiązany.

0

Spróbuj takiego podejścia: http://stackoverflow.com/a/19682690/1387438

0

Na razie wszystko sprawnie działa mi w oparciu o timeout(). Jeśli zaistnieje jak kolizja to pewnie postaram się wdrożyć inne rozwiązanie. Nie mnie dziękuje ponownie za odpowiedzi i wszystkie sugestie :)
Pozdrawiam

0

Tak z ciekawości jakie dane ci przychodzą? Binarne o stałej wielkości, czy może tekstowe zakończone znakiem końca linii?

0

Wszystko odbieram do QByteArray i rzutuje na unsigned char i takie też dane dostaje <0 ; 255>. Bez rzutowania przychodzą dane tupu char, czyli jak w urządzeniu ktoś w kodzie napisał char dane[10] = "blabla"; to odbieram blabla :). Głębiej nie badałem tematu.

0

Skoro dostajesz linie to rozwiązanie jest proste:

void COM_Configure::SLOT_ReciveData() {
    QSerialPort *serialPort = qobject_cast<QSerialPort *>(sender());
    while(serialPort && serialPort->canReadLine()) {
         emit lineWasRead(serialPort->readLine());
    }
}
0

Spróbuje rozwiązania. Mam jednak już bardzo rozbudowany kod w oparciu o timeout() działa dobrze. Jeśli kod będzie zbyt mało elastyczny postaram się wykorzystać zaproponowany sposób. Dziękuje za sugestie.

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