【问题标题】:QT Serial Port ReadingQT 串口读取
【发布时间】:2017-07-23 10:12:27
【问题描述】:

我正在尝试通过 USB 读取设备插头发送的数据。 首先我通过这个命令读取数据

  • sudo stty -F /dev/ttyUSB0 1200 sane parenb evenp cs7 -crtscts
  • cat /dev/ttyUSB0

而且数据是这样的

TGPHI_s -0,24 =

MESURES2 BT 4 SUP36 A

PTCOUR2 HPH /

现在我想通过 Qt5.3 程序读取数据

QSerialPort serial;
serial.setPortName("ttyUSB0");
if(!serial.setBaudRate(QSerialPort::Baud1200 , QSerialPort::Input))
    qDebug() << serial.errorString();
if(!serial.setDataBits(QSerialPort::Data7))
    qDebug() << serial.errorString();
if(!serial.setParity(QSerialPort::EvenParity))
    qDebug() << serial.errorString();
if(!serial.setFlowControl(QSerialPort::HardwareControl))
    qDebug() << serial.errorString();
if(!serial.setStopBits(QSerialPort::OneStop))
    qDebug() << serial.errorString();
if(!serial.open(QIODevice::ReadOnly))
    qDebug() << serial.errorString();
qDebug() << serial.bytesAvailable();
while(true)
{
    if (serial.isOpen()) {
        qDebug() << "Serial port is open...";
        QByteArray datas = serial.readAll();
        if (datas.size() == 0) {
            qDebug() << "Arrived data: 0";
        } else {
            for (int i = 0; i < datas.size(); i++){
                if (datas.at(i)) {
                    qDebug() << datas[i];
                }
            }
        }

    } else {
        qDebug() << "OPEN ERROR: " << serial.errorString();
    }
}
return 0;

答案是——>

"/dev/ttyUSB0"
0
Serial port is open...
Arrived data: 0
Serial port is open...
Arrived data: 0

所以我的程序没有捕获数据... 我的问题是:

  • 我是否错过了 QSerialPort 设置中的某些内容?
  • 如果没有,为什么没有通过 qDebug() 显示数据

编辑

感谢迈克,我终于可以阅读这个 USB 设备了!!! 这是我的最终代码

    QSerialPort serial;
serial.setPortName("ttyUSB0");
if(!serial.setBaudRate(QSerialPort::Baud1200))
    qDebug() << serial.errorString();
if(!serial.setDataBits(QSerialPort::Data7))
    qDebug() << serial.errorString();
if(!serial.setParity(QSerialPort::EvenParity))
    qDebug() << serial.errorString();
if(!serial.setFlowControl(QSerialPort::HardwareControl))
    qDebug() << serial.errorString();
if(!serial.setStopBits(QSerialPort::OneStop))
    qDebug() << serial.errorString();
if(!serial.open(QIODevice::ReadOnly))
    qDebug() << serial.errorString();
QObject::connect(&serial, &QSerialPort::readyRead, [&]
{
    //this is called when readyRead() is emitted
    //qDebug() << "New data available: " << serial.bytesAvailable();
    qDebug() << "New data available: " << serial.bytesAvailable();
    QByteArray datas = serial.readAll();
    qDebug() << datas;
});
QObject::connect(&serial,
                     static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>
                     (&QSerialPort::error),
                     [&](QSerialPort::SerialPortError error)
{
    //this is called when a serial communication error occurs
    qDebug() << "An error occured: " << error;
    return qApp->quit();
});


if(!serial.open(QIODevice::ReadOnly))
    qDebug() << serial.errorString();
return qApp->exec();

【问题讨论】:

    标签: c++ qt serial-port qt5 qtserialport


    【解决方案1】:

    Qt 中的大多数 IO 函数都是异步的。这意味着readAll() 不会等待数据到达。相反,它返回当前可用的数据(无需等待即可从设备读取的数据)。目前,你只是在无限循环中调用readAll(这使得线程,将所有时间都花在这个循环中,无法接收可能已经到达的新数据......)

    只有当您知道有新数据到达时,您才需要致电readAll。这可以通过两种方式实现:

    • 非阻塞异步方式:

      使用readyRead() 信号在设备中有新数据可用时获得通知,而不是永远循环。这就是你应该在 Qt 中做大多数事情的方式,以便能够对可能随时到达的多个事件采取行动。你的代码可以这样重写:

      #include <QtSerialPort>
      
      int main(int argc, char* argv[]){
          QCoreApplication a(argc, argv);
          QSerialPort serial;
          serial.setPortName("ttyUSB0");
          if(!serial.setBaudRate(QSerialPort::Baud1200))
              qDebug() << serial.errorString();
          if(!serial.setDataBits(QSerialPort::Data7))
              qDebug() << serial.errorString();
          if(!serial.setParity(QSerialPort::EvenParity))
              qDebug() << serial.errorString();
          if(!serial.setFlowControl(QSerialPort::HardwareControl))
              qDebug() << serial.errorString();
          if(!serial.setStopBits(QSerialPort::OneStop))
              qDebug() << serial.errorString();
          if(!serial.open(QIODevice::ReadOnly))
              qDebug() << serial.errorString();
          QObject::connect(&serial, &QSerialPort::readyRead, [&]
          {
              //this is called when readyRead() is emitted
              qDebug() << "New data available: " << serial.bytesAvailable();
              QByteArray datas = serial.readAll();
              qDebug() << datas;
          });
          QObject::connect(&serial,
                           static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>
                           (&QSerialPort::error),
                           [&](QSerialPort::SerialPortError error)
          {
              //this is called when a serial communication error occurs
              qDebug() << "An error occured: " << error;
              a.quit();
          });
      
          return a.exec();
          //     ^^^^^^^^
          //very important: starts the Qt main event loop
          //this makes all asynchronous stuff possible
      }
      
    • 阻塞同步方式:

      使用waitForReadyRead() 阻塞线程,直到新数据到达串行端口。这使得调用线程在新数据到达此串行端口之前无法执行任何操作。如果这个线程是一个 GUI 线程,这将使应用程序在那段时间没有响应。仅当您确定这是您想要的时才使用此方法。你的代码可以这样重写:

      #include <QtSerialPort>
      
      int main(int argc, char* argv[]){
          QCoreApplication a(argc, argv);
          QSerialPort serial;
          serial.setPortName("ttyUSB0");
          if(!serial.setBaudRate(QSerialPort::Baud1200))
              qDebug() << serial.errorString();
          if(!serial.setDataBits(QSerialPort::Data7))
              qDebug() << serial.errorString();
          if(!serial.setParity(QSerialPort::EvenParity))
              qDebug() << serial.errorString();
          if(!serial.setFlowControl(QSerialPort::HardwareControl))
              qDebug() << serial.errorString();
          if(!serial.setStopBits(QSerialPort::OneStop))
              qDebug() << serial.errorString();
          if(!serial.open(QIODevice::ReadOnly))
              qDebug() << serial.errorString();
          qDebug() << serial.bytesAvailable();
          while(serial.isOpen())
          {
              if(!serial.waitForReadyRead(-1)) //block until new data arrives
                  qDebug() << "error: " << serial.errorString();
              else{
                  qDebug() << "New data available: " << serial.bytesAvailable();
                  QByteArray datas = serial.readAll();
                  qDebug() << datas;
              }
          }
          return 0;
      }
      

    【讨论】:

    • 感谢您的回复,但始终存在没有数据显示的问题。我采用异步方式,唯一的想法就是这样。 pastebin.com/RW7PVNMN 在新数据可用之后每个之间都有一个空格:1.可能来自参数(baudRate,databits ...)。您认为这与 stty 命令中的选项匹配吗?
    • @tlebreton ,我改变了输出的方式,这可以更好地表示接收到的数据(从而帮助弄清楚发生了什么)。我认为参数是相同的。也许尝试使用serial.setStopBits(QSerialPort::TwoStop) 而不是一个停止位,因为我不确定sane 如何在stty 中设置它。
    • 我发现了我的错误(我感到羞耻)。在 setBaudRate 我不需要 QSerialPort::Input。没有显示,没有我想要的一切感谢迈克的帮助,我很感激
    • @tlebreton,不客气。我不明白为什么会导致问题。 AFAIK,这意味着波特率设置仅适用于输入数据(即,正在读取的数据),这应该是我们的目标,不是吗?无论如何,我已经更新了答案:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多