Russian Qt Forum
Ноябрь 23, 2024, 03:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Qextserialport и waitForReadyRead  (Прочитано 12629 раз)
em
Гость
« : Июнь 16, 2008, 16:27 »

Всех приветствую!

Для работы с COM-портом использую QextSerialPort v1.1,
после передачи данных в порт, ожидаю ответа, при помощи ф-ии
Цитировать
bool waitForReadyRead(int msec)
Код:
if (port->waitForReadyRead(1000)) {
    receiveMsg();
}
но почему-то waitForReadyRead никогда не возвращает true
подскажите что не так?
Записан
em
Гость
« Ответ #1 : Июнь 16, 2008, 17:44 »

попытался сделать типа waitReadyRead(1000);
но почемуто не испускается сигнал readyRead();
делал так
Код:
connect(port, SIGNAL(readyRead()), this, SLOT(setReady()));
.............................
waitReadyRead(1000);
if (ready) {
receiveMsg();
}
..............................
void Thread::setReady()
{
ready = true;
emit sendMessage("eee");
}

void Thread::waitReadyRead(int msec)
{
QTime timer;
timer.start();
while ( (timer.elapsed() < msec)) {
if (ready)
break;
msleep(1);
}
}
но тогда все упирается в испускание сигнала readyRead(); которого не происходит почему-то)
Записан
Mikhail
Программист
*****
Offline Offline

Сообщений: 587


Просмотр профиля
« Ответ #2 : Июнь 16, 2008, 21:43 »

Всех приветствую!

Для работы с COM-портом использую QextSerialPort v1.1,
после передачи данных в порт, ожидаю ответа, при помощи ф-ии
Цитировать
bool waitForReadyRead(int msec)
Код:
if (port->waitForReadyRead(1000)) {
    receiveMsg();
}
но почему-то waitForReadyRead никогда не возвращает true
подскажите что не так?

Используй port->bytesAvailable() для проверки данных в буфере порта.
Для приема желательно организовать отдельный поток в котором в функции run() и делать эту проверку в цикле.
Записан
em
Гость
« Ответ #3 : Июнь 17, 2008, 08:23 »

Используй port->bytesAvailable() для проверки данных в буфере порта.
Для приема желательно организовать отдельный поток в котором в функции run() и делать эту проверку в цикле.
Работа с com портом у меня в отдельном потоке,
Ага кстати можно же делать проверку в цикле с таймоутом моленько по другому, типа
Код:
void Thread::waitReadyRead(int msec)
{
QTime timer;
timer.start();
while ( (timer.elapsed() < msec)) {
if (port->bytesAvailable() > 0) {
ready = true;
break;
}
msleep(1);
}
}

Интересно почему сигнал readyRead() не испускается?
Записан
Mikhail
Программист
*****
Offline Offline

Сообщений: 587


Просмотр профиля
« Ответ #4 : Июнь 17, 2008, 10:20 »

Используй port->bytesAvailable() для проверки данных в буфере порта.
Для приема желательно организовать отдельный поток в котором в функции run() и делать эту проверку в цикле.
Работа с com портом у меня в отдельном потоке,
Ага кстати можно же делать проверку в цикле с таймоутом моленько по другому, типа
Код:
void Thread::waitReadyRead(int msec)
{
QTime timer;
timer.start();
while ( (timer.elapsed() < msec)) {
if (port->bytesAvailable() > 0) {
ready = true;
break;
}
msleep(1);
}
}

Интересно почему сигнал readyRead() не испускается?

void QIODevice::readyRead ()   [signal]
This signal is emitted once every time new data is available for reading from the device. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.
readyRead() is not emitted recursively; if you reenter the event loop or call waitForReadyRead() inside a slot connected to the readyRead() signal, the signal will not be reemitted (although waitForReadyRead() may still return true).
Note for developers implementing classes derived from QIODevice: you should always emit readyRead() when new data has arrived (do not emit it only because there's data still to be read in your buffers). Do not emit readyRead() in other conditions.

А в qextserialport этот сигнал не испускается, так как такова реализация qextserialport. Как написано в документации испускать этот сигнал должен класс производный от QIODevice.
Записан
em
Гость
« Ответ #5 : Июнь 17, 2008, 10:35 »

Понятно,
to Mikhail Спасибо!
Записан
em
Гость
« Ответ #6 : Июнь 21, 2008, 10:29 »

Ага кстати можно же делать проверку в цикле с таймоутом моленько по другому, типа
Код:
void Thread::waitReadyRead(int msec)
{
QTime timer;
timer.start();
while ( (timer.elapsed() < msec)) {
if (port->bytesAvailable() > 0) {
ready = true;
break;
}
msleep(1);
}
}
оказалось что такая реализация работает не очень корректно, получается так, что например должно прийти сообщение 9 байт а при использовании этой функции получается что port->bytesAvailable() срабатывает и считывается 8 байт а другой байт считывается как второе сообщение в виде одного оставшегося байта.
А вот если использовать просто msleep(int msec) засыпая допустим на 60 мс, то сообщение читается как одно все 9 байт.
Порт в клиенте и севере открывается в режиме QIODevice::ReadWrite | QIODevice::Unbeffered
по идее раз данные не буферизуются и то они отправляются все разом и должны приниматься тоже разом

Есть идеи как можно это исправить?
Записан
Mikhail
Программист
*****
Offline Offline

Сообщений: 587


Просмотр профиля
« Ответ #7 : Июнь 21, 2008, 11:01 »

Ага кстати можно же делать проверку в цикле с таймоутом моленько по другому, типа
Код:
void Thread::waitReadyRead(int msec)
{
QTime timer;
timer.start();
while ( (timer.elapsed() < msec)) {
if (port->bytesAvailable() > 0) {
ready = true;
break;
}
msleep(1);
}
}
оказалось что такая реализация работает не очень корректно, получается так, что например должно прийти сообщение 9 байт а при использовании этой функции получается что port->bytesAvailable() срабатывает и считывается 8 байт а другой байт считывается как второе сообщение в виде одного оставшегося байта.
А вот если использовать просто msleep(int msec) засыпая допустим на 60 мс, то сообщение читается как одно все 9 байт.
Порт в клиенте и севере открывается в режиме QIODevice::ReadWrite | QIODevice::Unbeffered
по идее раз данные не буферизуются и то они отправляются все разом и должны приниматься тоже разом

Есть идеи как можно это исправить?

Не надо ничего исправлять. Это может быть влиянием операционной системы. Она может заняться чем то другим. Смотрел передачу по линии и видел рваные пачки байт. Все время разные.

Предлагаю вернуться к  чтению port->bytesAvailable() в основном цикл функции run() потока. Не надо засыпать и ничего не пропустишь.

Пример из рабочего проекта:

Код:
void qPThRead::run()
{

int i;
priem = true;
recivString="";
int len=0;
if ( ComPort != NULL )
{
   
while (priem) { 
    if ( !stopReciv )
    {

    len=0;
    len = ComPort->bytesWaiting() ;
               if ( len == ( unsigned int ) -1 ) continue;
    if (len >0)
    {
stopReciv = true;
mutex.lock();



for (i=0; i<len; i++)
{
    recivString +=ComPort->getch();
}

qPThReadEvent * event = new qPThReadEvent(1001);
event->String = recivString;
event->PortName = PortName;

QApplication::postEvent(TargetWidget, event);

recivString = "";
mutex.unlock();
}
   
    }
    }
    }
   
}
   
« Последнее редактирование: Июнь 21, 2008, 12:12 от pastor » Записан
Hammer
Гость
« Ответ #8 : Ноябрь 19, 2008, 20:11 »

А как прикрутить чтение в отдельном потоке к нижеследующему коду? Я хотел бы реализовать софтовый флоу контроль, т.е. отправляю пакет фиксированной длины и жду ответа от устройства, что оно его приняло и записало или таймаут и выход из процедуры отправки (ну или повторная отправка n раз). Тут лучше всего подходит метод waitForReadyRead(), но его надо писать самому, в чем я не силен пока что. буду благодарен за любую помощь, включая готовые куски кода =)

Код
C++ (Qt)
void Mainwin::sendData()
{
   char data[1024];
   QByteArray baSend;
   int numBlocks = ceil((float)dataToSend().length() / 64);
 
   QProgressDialog progress(tr("Sending Data..."), tr("Abort Sending"), 0, numBlocks, this);
   progress.setWindowModality(Qt::WindowModal);
 
 
   for (int i = 0; i < numBlocks; i++) {
       progress.setValue(i);
       baSend.clear();
       baSend.append(0xAA); //startByte
       baSend.append(i>>8);  //pageNum
       baSend.append(i & 0x0F);  //pageNum
       baSend.append(dataToSend().mid(i*64, 64));  //64 bytes of data
       baSend.append(0xDD); //crc
       baSend.append(0xCC); //crc
 
       if (progress.wasCanceled())
           break;
 
       port->write(baSend, baSend.length());
 
       // wait for an answer
       // or timeout  
 
   }
 
   progress.setValue(numBlocks);
}
 
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.214 секунд. Запросов: 23.