2014-02-08 2 views
0

Мне нужно разработать программу на C++ для встроенной процессорной системы на базе FriendlyARM. Я использую Qt Creator 3.0.0 (на основе Qt 5.2.0) для настольного компьютера. Моя программа должна быть в состоянии читать из последовательного порта в Mini2440 FriendlyARM-процессоре.Неисправность при чтении из последовательного порта с использованием QSerialPort

Прежде чем перейти в целевую систему (встроенную систему), я попытался прочитать и записать из/в последовательный порт на моем ноутбуке. Моя основная проблема заключается в том, как читать из последовательного порта. Как вы знаете, новые компьютеры и ноутбуки не имеют последовательного порта, поэтому я пытаюсь имитировать программирование последовательного порта, используя ручной кабель USB-to-serial. Когда последовательный кабель USB подключен, он распознается как «/ dev/ttyUSB0» на Ubuntu. Кажется, это хорошо работает. Обратите внимание, что другой конец кабеля (последовательный порт) не подключен ни к чему.

Мой первый вопрос: нормально ли настроить такой кабель, или мне нужно подключить его к другому устройству? Я пытаюсь написать/dev/ttyUSB0 каждые 10 секунд и прочитать данные. Я закончил следующий код:

void MainWindow::refreshNotificationArea() 
{ 
    generateNotifAreaData(); // a typical random data-generator 
    QList<QSerialPortInfo> L = QSerialPortInfo::availablePorts(); 
    for (auto e : L) 
     qDebug() << e.portName() << '\n'; // it prints 1 serial port: :ttyUSB0 
    // write to the port 
    QSerialPort notifAreaPort; 
    // 1. set properties 
    notifAreaPort.setBaudRate(QSerialPort::Baud9600); 
    notifAreaPort.setStopBits(QSerialPort::OneStop); 
    notifAreaPort.setParity(QSerialPort::NoParity); 
    notifAreaPort.setDataBits(QSerialPort::Data8); 
    notifAreaPort.setFlowControl(QSerialPort::NoFlowControl); 
    QObject::connect(&notifAreaPort,SIGNAL(error(QSerialPort::SerialPortError)), 
    this, SLOT(errorReport(QSerialPort::SerialPortError))); 
    notifAreaPort.setPortName(serial_device.c_str()); 
    // 2. open port 
    notifAreaPort.open(QIODevice::ReadWrite); 
    if (!notifAreaPort.isOpen()) 
     qDebug() << "Open failed"; // open is OK, no error message printed 

    string s = convertNotifAreadData2Str(); 
    qDebug() << "Generated data " << s.c_str(); // OK 
    int a = notifAreaPort.write(s.c_str()); // write done 
    qDebug() << "Write count" << a; // OK 

    // now read the info 

    QByteArray ba = notifAreaPort.readLine(3); // read failed 
    QSerialPort::SerialPortError err = notifAreaPort.error(); 
    qDebug() << "Error code" << err; 
    qDebug() << "What? " << notifAreaPort.errorString(); 
    qDebug() << "Read count " << ba.size(); // 0 

    notifAreaPort.close(); 
} 

void MainWindow::errorReport(QSerialPort::SerialPortError error) 
{ 
    if(error!=0) 
     qDebug()<<"ERROR:"<<endl<<error; // nothing printed 
} 

Запись в последовательный порт в порядке. но иногда возникают проблемы с чтением «Нет такого файла или каталога»! иногда «Файл временно unavalable Странная вещь notifAreaPort.error() возвращает 0, и это не означает, что никакой ошибки произошла

Мысли

-!? Саид Amrollahi Boyouki

ответ

0

Вы не можете писать, а затем читать с QSerialPort в той же функции.

Есть два метода, которые я использую для QSerialPort обработки:

METHOD ONE создать и открыть свой QSerialPort объект. Установите QTimer с тайм-аутом около 50 мс или около того (в зависимости от оборудования).

Подключите сигнал readyRead() к слоту, который в основном просто считывает все данные в буфер (QByteArray идеально подходит для этого). Слот останавливает QTimer, считывает все данные, доступные с помощью readAll(), а затем перезапускает QTimer и возвращается.

Подключите timeout сигнал QTimer к функции обработки прочитанных байтов ввода.

Предпосылка заключается в том, что в конечном итоге все данные будут получены, и QTimer будет тайм-аут, после чего у вас будут все ваши данные в буфере для обработки.

METHOD TWO слот, который обрабатывает readyRead() сигнала может проверить все данные в буфере для некоторых «маркера», который обозначает, что некоторые порции данных полностью прибыли. Многие устройства используют 0x0D или 0x0d0x0A в качестве делителя. Другие используют NULL 0x00 или какой-либо другой байт.

Оцените буфер на каждой итерации слота для обработки readyRead().

В этом примере показан второй вариант, и он хорошо подходит для небольших чтений.

r_port = new QSerialPort(this); 
r_port->setPortName("COM3"); 
r_port->setBaudRate(QSerialPort::Baud9600); 
r_port->setDataBits(QSerialPort::Data8); 
r_port->setParity(QSerialPort::NoParity); 
r_port->setStopBits(QSerialPort::OneStop); 
r_port->setFlowControl(QSerialPort::NoFlowControl); 
if (r_port->open(QSerialPort::ReadWrite)) 
{ 
    connect(r_port, &QSerialPort::readyRead, this, &MYPROG::on_readyRead); 
    connect(r_port, &QSerialPort::errorOccurred, this, &MYPROG::breakCaught); 
} 
else 
{ 
    QMessageBox::critical(this, "SERIAL PORT NOT CONNECTED", "Unable to connect to the radio.\n\nPlease check your connections\nand configuration and try again."); 
    return; 
} 

void MYPROG::on_readyRead() 
{ 
// keep reading until we get a \r\n delimiter 
    rxBytes.append(r_port->readAll()); 
    qDebug()<<"raw rxBtes"<<rxBytes; 
    if(!rxBytes.contains("\r\n")) 
    { 
     return; 
    } 
    int end = rxBytes.lastIndexOf("\r\n") + 2; 
    QStringList cmds = QString(rxBytes.mid(0, end)).split("\r\n", QString::SkipEmptyParts); 
    rxBytes = rxBytes.mid(end); 
    foreach(QString cmd, cmds){ 
     qDebug()<<"serial read"<<cmd; 
    } 
} 

Это позволяет QSerialPort следует читать при поступлении данных, а затем программа может вернуться в цикл обработки событий, чтобы сохранить графический интерфейс от его недоступности. Типичные серийные чтения являются небольшими и имеют короткую продолжительность, поэтому замораживание UI редко происходит с использованием этих методов.

0

«рамы сделанный USB для последовательного адаптера »- звучит интересно. Вы уверены, что это работает правильно? Я думаю, что это хорошая идея для подключения PIN 2 (Rx) и 3 (Tx), поэтому вы получаете данные. Теперь вы можете протестировать свое устройство с помощью любое другое программное обеспечение терминала. Я использую для последовательных портов всегда сигнал readyRead(), и я проверяю перед чтением с помощью port-> bytesAvailabl e(). И я открываю порт с портом -> open (QIODevice :: ReadWrite | QIODevice :: Unbuffered).

+0

Благодарим вас за отзыв Matthias. Я проверю кабель позже. Ответьте на мой первый вопрос. Просто для проверки чтения и записи последовательного порта, все в порядке, один конец последовательного кабеля, подключенного к ноутбуку, и другой конец, не подключенный к устройству (какое бы последовательное устройство)? –

+0

Matthias. Из QSerialPort :: open() doc: –

+0

Внимание: режим должен быть QIODevice :: ReadOnly, QIODevice :: WriteOnly или QIODevice :: ReadWrite. Другие режимы не поддерживаются. –

0

Есть несколько проблем в вашем коде, но я выделю наиболее важные из них:

  • Вы устанавливаете параметры перед тем открытия. Это должно произойти после открытие. Именно так API был составлен с грустью, но мы в процессе его обновления.

  • Вы должны command line examples for reading, который я добавил в 5.2? Кажется, вы не знаете, как читать, и это даст вам простой пример. Короче: вы в основном пытаетесь прочитать, прежде чем пишите потенциально даже готово.

Смежные вопросы