QSerialPort в цикле while?

У меня есть функция, которая отправляет данные через RS-232 в Hyperterminal. Функция корректно работает вне цикла while, однако в цикле while она отправляет только в первый раз, после чего ничего не отправляет.

    qDebug() << MESSAGE;
    int choice;
    std::cin >> choice;

    while( choice != 3 )
    {
        switch (choice)
        {
            case 1:
                // Ready to send data 
                port->write("QSerial Port!\r\n");
                break;
            case 2:
                qDebug() << "Todo...";
                break;
            case 3:
                break;
            default:
                qDebug() << "Invalid Choice ...";
        }
        qDebug() << MESSAGE;
        std::cin >> choice;
    }

Редактировать:

#include <QCoreApplication>
#include <iostream>
#include <QDebug>
#include <QSerialPort>

const char MESSAGE[] = "\n----- New Menu ----"
                       "\n1- Send Data     \n"
                       "2- Receive Data    \n"
                       "3- Quit:           \n";


int main(int argc, char *argv[])
{
    QCoreApplication  app(argc, argv);

    QSerialPort *port = new QSerialPort;
    port->setPortName("COM4");


    // Check the validity of the port
    if ( !port->open(QIODevice::ReadWrite) )
    {
        qDebug() << "\nError: " << port->portName() << " port can't be opened ...";
        return -1;
    }else{
        qDebug() << '\n' << port->portName() << " port has been opened successfully ...";
        port->setBaudRate(QSerialPort::Baud9600);
        port->setStopBits(QSerialPort::OneStop);
        port->setDataBits(QSerialPort::Data8);
        port->setParity(QSerialPort::NoParity);
        port->setFlowControl(QSerialPort::NoFlowControl);
        qDebug() << port->portName() << " port has been configured correctly ...";
    }

    qDebug() << MESSAGE;
    int choice;
    std::cin >> choice;

    while( choice != 3 )
    {
        switch (choice)
        {
            case 1:
            {
                // Ready to send data 
                if ( port->write("QSerial Port!\r\n", qstrlen("QSerial Port!\r\n")) == -1)
                {
                    qDebug() << port->errorString();
                }
                //port->bytesWritten(strlen("QSerial Port!\r\n"));
                port->waitForBytesWritten(-1);
                //qDebug() << port->errorString();
            }
                break;
            case 2:
                qDebug() << "Todo...";
                break;
            case 3:
                break;
            default:
                qDebug() << "Invalid Choice ...";
        }
        qDebug() << MESSAGE;
        std::cin >> choice;
    }

    qDebug() << "\n Goodbye ....";
    port->close();
    delete port;
    return app.exec();
}

person CroCo    schedule 16.03.2014    source источник
comment
Пожалуйста, покажите вывод port->errorString(). Также, пожалуйста, покажите, как вы настраиваете объект qtserialport, как вы его открываете. Вы используете QtSerialPort 5.2.1, верно?   -  person lpapp    schedule 17.03.2014
comment
Это моя функция, чтобы проверить ошибку, но я ничего не получил. Я не думаю, что это ошибка, однако я думаю, что вы сказали правильно, что проблема со временем ожидания для отправки следующих данных.   -  person CroCo    schedule 17.03.2014
comment
Какая это операционная система? Это 32 или 64 бит? Это QtSerialPort 5.2.1 или с Qt 4? Usb серийный или родной?   -  person lpapp    schedule 17.03.2014
comment
64-битная Windows, QtSerialPort 5.2.1. Драйвер виртуального последовательного порта   -  person CroCo    schedule 17.03.2014
comment
Виндовс 7 или что-то другое? Почему бы вам не проверить на потерю данных, просто -1? Кроме того, вы, похоже, не проверяете возвращаемое значение метода waitForBytesWritten. Удачен ли этот метод? Кроме того, когда вы печатаете errorString(), лучше поместить туда какой-нибудь префикс, чтобы не потеряться в выводе. Можете ли вы воспроизвести эту проблему без cin и ввода, просто запустив запись в цикле, повторяющемся трижды? Кроме того, лучше проверить все настройки после открытия ИМХО. Кто-нибудь из них терпит неудачу? Кстати, это C++ и полурайи. Здесь не нужно явно закрывать порт.   -  person lpapp    schedule 17.03.2014
comment
Это Windows 7. Я думаю, что проблема была в буфере. Каждый раз, когда я отправляю данные, мне нужно очистить буфер, поэтому я сделал это, используя port->clear(). Единственная проблема сейчас в том, что каждый раз, когда я отправляю Q, я получаю QQ. Почему я получаю двойные данные?   -  person CroCo    schedule 17.03.2014
comment
Это также происходит с реальным последовательным портом, например, родным sub-9 или usb-serial, например PL2303?   -  person lpapp    schedule 17.03.2014
comment
Я использую Hyperterminal для проведения этого эксперимента и драйвер виртуального последовательного порта для установления соединения.   -  person CroCo    schedule 18.03.2014
comment
Я не совсем уверен в размере буфера. Я думаю, что буфер будет отправлен после его заполнения, но я понимаю последовательный порт так, что данные отправляются байт за байтом.   -  person CroCo    schedule 18.03.2014
comment
Можете ли вы попробовать использовать собственный последовательный порт или USB-порт для быстрого теста, чтобы увидеть, является ли это поведение специфичным для драйвера последовательного порта Vierual?   -  person lpapp    schedule 18.03.2014
comment
К сожалению, сейчас у меня нет оборудования. Вы предлагаете какое-либо другое программное обеспечение для драйвера гипертерминала или виртуального последовательного порта? Другой вопрос, знаете ли вы, как получить размер выходного буфера?   -  person CroCo    schedule 18.03.2014
comment
Я использовал другое программное обеспечение, а именно шпатлевку. Результат тот же, так что теперь я уверен, что проблема не в гипертерминале. Подозреваю Qt. Какие-либо предложения?   -  person CroCo    schedule 19.03.2014
comment
Проблема решена. Проблема заключалась в драйвере виртуального последовательного порта HHD. Он повторяет любые отправляемые данные, и для этого программного обеспечения нет даже настроек.   -  person CroCo    schedule 19.03.2014
comment
Понизить? Почему? Я ясно объяснил проблему и продемонстрировал свои усилия, чтобы приступить к работе. Это не честно.   -  person CroCo    schedule 18.04.2014


Ответы (2)


Ваш код имеет следующие недостатки:

1) Вы не обрабатываете ошибки.

2) Вы не проверяете возвращаемое значение операции записи.

3) Вы, похоже, не ждете программно, прежде чем писать снова. Это неправильно. Либо используйте синхронизирующий сигнал waitForBytesWritten, либо асинхронный сигнал bytesWritten, чтобы дать зеленый свет для следующей записи.

Наиболее критичен, пожалуй, последний пункт. Это приведет к «случайному» поведению при отправке данных. В этом особом случае он, вероятно, будет отправлен последовательно, так как ожидание ввода, вероятно, займет у вас больше времени, но это все еще не стабильный и надежный код для написания.

person lpapp    schedule 16.03.2014
comment
Я думаю, что вы правы насчет последнего пункта, который вы упомянули. если я использую port->waitForBytesWritten(-1);, он делает именно то, что я ищу, однако ведет себя странно. Например, в первый раз он отправляет QSerial Port!\r\n один раз. Когда я отправляю его во второй раз, сообщение дублируется. В третий раз сообщение утраивается и так далее. - person CroCo; 17.03.2014
comment
@CroCo: покажите весь код, который воспроизводит проблему. - person lpapp; 17.03.2014

Не могу полностью согласиться с пунктом (3). Нет ничего, что говорило бы о том, что вы не можете сделать вторую запись, пока первая еще не завершена. В принципе данные должны быть просто добавлены в очередь передачи. Это все равно, что сказать: «Вы не можете снова записать в этот файл, пока предыдущие данные не будут записаны на диск». У меня была аналогичная проблема с qtserial, где я делал:

while (..)
{
    <send data>
    <receive data>
}

Оказывается, вы ДОЛЖНЫ выполнить qApp->processEvents(), прежде чем вы сможете что-либо получить или прежде чем вы сможете записать новые данные. Я ожидал такого же поведения, как при чтении/записи файла. Для меня qtserial НЕ ведет себя так, как вы ожидаете от устройства.

person Gert    schedule 14.04.2014
comment
Ты прав. После использования qApp->processEvent() он ведет себя так, как я ожидал. Странно, что в документации ничего не сказано об использовании qApp-›processEvents() для класса QSerialPort. - person CroCo; 18.04.2014
comment
@CroCo: между прочим, я являюсь одним из участников QtSerialPort вместе с Сергеем, и этот ответ не кажется правильным, насколько я могу сказать. Явная обработка событий не требуется. Даже если кажется, что это работает, это неправильный путь. Я все еще придерживаюсь того, что я сказал, будет правдой. Так была задумана библиотека. В общем, вы можете писать непрерывно, но в этом случае, я думал, вы будете обрабатывать сообщения кусками на другой стороне? - person lpapp; 18.04.2014
comment
@LaszloPapp, еще раз большое спасибо за совет. Не могли бы вы предоставить мне простой пример, чтобы я мог его протестировать. Теоретически то, что сказал Герт, верно, но я все еще не понимаю класс QSerialPort. Я видел, как многие люди жалуются на цикл while в Qt в целом. По крайней мере, для новичков в этом вопросе есть что-то скрытое. - person CroCo; 18.04.2014