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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Трудность с библиотекой QSerialDevice  (Прочитано 18457 раз)
Piknik
Гость
« : Декабрь 02, 2011, 11:25 »

Здравствуйте. Проблемка такая...принимаю по ком-порту 6 байт данных раз в 4 сек. Если использую режим ReadOnly или AbstractSerial::ReadOnly| AbstractSerial::Unbuffered посылка приходит частями, те:
Код:
Bytes_Available: 3 
Bytes_Available: 3

или
Код:
Bytes_Available: 2 
Bytes_Available: 4

 Любые игры с "setCharIntervalTimeout(10)"  не помогают... Почему сообщение разделяется на куски?

Код:
MyMainWindow::MyMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MyMainWindow)
{
    ui->setupUi(this);
...
serialPort->open(AbstractSerial::ReadOnly| AbstractSerial::Unbuffered);
...
serialPort->setCharIntervalTimeout(10);  
connect(serialPort, SIGNAL(readyRead()), this, SLOT(serialDataReady()));
}

void MyMainWindow::serialDataReady()
{
    uint8_t num = serialPort->bytesAvailable();    // сколько байт в буфере
    qDebug() << "Bytes_Available:" << num;
    QByteArray ba;


     if ((serialPort->bytesAvailable() > 0))
     {
          ba.clear();
          ba = serialPort->read(num);
          qDebug() << "Readed is : " << ba.size() << " bytes";
     }

    serialPort->reset();


}
« Последнее редактирование: Декабрь 02, 2011, 11:47 от Piknik » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Декабрь 02, 2011, 13:22 »

Цитировать
Любые игры с "setCharIntervalTimeout(10)"  не помогают...
Потому, что надо играться с setTotalReadConstantTimeout(),
а про setCharIntervalTimeout() нужно забыть.




Записан

ArchLinux x86_64 / Win10 64 bit
Piknik
Гость
« Ответ #2 : Декабрь 02, 2011, 13:48 »

Тоже не помогает...
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #3 : Декабрь 02, 2011, 14:17 »

Какую версию библиотеки используете и какая ОС?

Код
C++ (Qt)
#if defined (Q_OS_UNIX)
       // Method setTotalReadConstantTimeout() not supported in *.nix.
       if (port->openMode() & AbstractSerial::Unbuffered)
           port->setCharIntervalTimeout(5000);//5 msec
#elif defined (Q_OS_WIN)
       if (port->openMode() & AbstractSerial::Unbuffered)
           port->setTotalReadConstantTimeout(100); //100 msec
#endif
 

А вообще, пора уже переходить на новье - ветку 2.0.
« Последнее редактирование: Декабрь 02, 2011, 14:23 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Piknik
Гость
« Ответ #4 : Декабрь 02, 2011, 14:23 »

Там где 2 библ qserialdevice и qserialdeviceenumerator . Вторую не крепил, не критично? Где посмотреть версию? ОС: Windows XP
« Последнее редактирование: Декабрь 02, 2011, 14:26 от Piknik » Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #5 : Декабрь 02, 2011, 14:26 »

Цитировать
Где посмотреть версию?

тут,
справа внизу будут все доступные версии.

Если используете ту ветку что сейчас - то качайте master бранч,
если хотите самое новье - то 2.0 бранч.

Записан

ArchLinux x86_64 / Win10 64 bit
Piknik
Гость
« Ответ #6 : Декабрь 02, 2011, 14:32 »

ну судя по всему у меня и так мастер бранч...
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #7 : Декабрь 02, 2011, 14:34 »

Значит напиши побольше в

Код
C++ (Qt)
port->setTotalReadConstantTimeout(100); //100 msec
Записан

ArchLinux x86_64 / Win10 64 bit
Piknik
Гость
« Ответ #8 : Декабрь 02, 2011, 14:44 »

Да ощущение, что ему все равно...(( сколько не поставить..может я не так подцепляю библиотеку...
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #9 : Декабрь 02, 2011, 15:10 »

Ну тогда - ХЗ, проверяй в отладчике.
Записан

ArchLinux x86_64 / Win10 64 bit
Piknik
Гость
« Ответ #10 : Декабрь 05, 2011, 12:13 »

С новой библиотекой 2.0 другой момент. Все вроде принимает "Bytes_Available: 6 ", но не генерирует сигнал "readyRead()" и не уходит в обработку слота. В чем может быть причина?
Код:
 MyMainWindow::MyMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MyMainWindow)
{
    ui->setupUi(this);
    QIODevice::OpenMode mode = QIODevice::ReadOnly;
    mode |= QIODevice::Unbuffered;

    if (!myPortCom->open(mode))                                                  // Открываем порт
    {
        QMessageBox::critical(this, QString::fromLocal8Bit("Com port"),
                              QString::fromLocal8Bit("Не могу открыть порт ")+ comPort, QMessageBox::Ok);
        ui->statusBar->showMessage(QString::fromLocal8Bit("Error opening COM port!"));
    }
    else                                                 
    {

        myPortCom->setRate(9600);                 
        myPortCom->setDataBits(SerialPort::Data8);
        myPortCom->setParity(SerialPort::NoParity);
        myPortCom->setStopBits(SerialPort::OneStop);
        myPortCom->setFlowControl(SerialPort::NoFlowControl);
        myPortCom->waitForReadyRead(5000);
   
        connect(myPortCom, SIGNAL(readyRead()), this, SLOT(serialDataReady()));
    }
    uint8_t num = myPortCom->bytesAvailable();                     // байт в буфере
    qDebug() << "Bytes_Available:" << num;

void MyMainWindow::serialDataReady()
{
     qDebug() << "Recieved";
}
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #11 : Декабрь 05, 2011, 12:33 »

Потому, что connect делаешь после того, как отработает waitForReadyRead(), т.е. после того как сигнал уже излучился.
В винде такая есть особенность, что readyRead() срабатывает однажды при приеме символа. И если заранее не сделать
connect - то никакого сигнала не получишь.

Поэтому нужно делать connect сразу после создания объекта порта.

И непонятно зачем вообще использовал waitForReadyRead() + connect - это хрень собачья. Почитай
документацию Qt в плане того, в каких случаях необходимо использовать waitForReadyRead().

Так же в 2.0 не используй.
Код
C++ (Qt)
mode |= QIODevice::Unbuffered;
 

С версией 2.0 идут примеры /test/guiapp - вот там и проверь принимаются или нет твои 6 байт.
Записан

ArchLinux x86_64 / Win10 64 bit
Piknik
Гость
« Ответ #12 : Декабрь 05, 2011, 14:58 »

Спасибо за помошь. Убрал waitForReadyRead, снова делит пакет пополам...есть какой то аналог setTotalReadConstantTimeout() в этой библиотеке, не могу найти..ну или как выставить этот таймаут, чтоб пакет целиком прочелся...или же хотя бы читался по байту...ну не догоняю..
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #13 : Декабрь 05, 2011, 15:41 »

Цитировать
есть какой то аналог setTotalReadConstantTimeout() в этой библиотеке

Нету. Он и не нужен. В этой новой версии чтение происходит "мгновенно",
без всяких таймаутов, т.е. не блокирующий режим.

Поэтому, при приеме сигнала readyRead() запускай QTimer::singleShot() с таймаутом, при котором гарантированно
придет весь твой пакет. Коннекть этот singleShot() на слот чтения данных и читай.
Т.е. singleShot() сработает с некоторой задержкой от момента первого поступления данных.

Вот тебе обсуждение: http://www.prog.org.ru/index.php?topic=9537.msg133030#msg133030
см. от поста №618 и ниже.
« Последнее редактирование: Декабрь 05, 2011, 15:45 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
BRE
Гость
« Ответ #14 : Декабрь 05, 2011, 15:58 »

Я вообще не могу понять в чем собственно проблема. Улыбающийся
Пришел сигнал readyRead, проверил сколько байт доступно (bytesAvailable), если меньше требуемых 6, то просто выходим из слота и ждем пока приедет остальная часть пакета (снова вызовется readyRead).
Это абсолютно нормальный порядок работы при получении удаленных данных.
« Последнее редактирование: Декабрь 05, 2011, 17:30 от BRE » Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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