【问题标题】:Double way Serial communication between Arduino and Qt 5.7Arduino和Qt 5.7之间的双向串行通信
【发布时间】:2016-10-25 17:56:56
【问题描述】:

我正在尝试将数据从 Arduino 传输到 C++ Qt5.7 以及从 Arduino 传输到 C++ Qt5.7 (MinGW) 程序。

我能够毫无问题地将数据从 QT 传输到 ARDUINO。 Arduino 完美闪烁。

另一方面,从 ARDUINO 传输到 QT 的数据并不总是预期的(当它应该是“LED OFF”时发送“LED ON”),有时它根本不通信!

QT代码:

#include <QCoreApplication>
#include <QDebug>

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QThread>

#include <iostream>
using namespace std;

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

    QSerialPort serial;
    serial.setPortName("COM6");
    serial.setBaudRate(9600);
    serial.setDataBits(QSerialPort::Data8);
    serial.setParity(QSerialPort::NoParity);
    serial.setStopBits(QSerialPort::OneStop);
    serial.setFlowControl(QSerialPort::NoFlowControl);

    if(serial.open(QSerialPort::ReadWrite))
    {
        string c;
        QByteArray s;
        QByteArray received;
        while(true)
        {
            qDebug("TRUE");
            //WRITE
            cin >> c;
            cout << endl;
            s = QByteArray::fromStdString(c);
            serial.write(s);
            serial.waitForBytesWritten(-1);

            //serial.flush();

            s = serial.readAll();
            serial.waitForReadyRead(-1);
            cout << s.toStdString() << endl;

            //serial.flush();
        }
    }
    else
    {
        QString error = serial.errorString();
        cout << error.toStdString() << endl;
        qDebug("FALSE") ;
    }


    serial.close();

    return a.exec();
}

ARDUINO 代码:

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {   
  delay(1000); // wait for a second
}

void serialEvent() 
{
  char inChar;
  while (Serial.available()) 
  {
    // get the new byte:
    inChar = (char)Serial.read();
    if(inChar == 'a')
    {
      digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    }
    else
    {
      digitalWrite(LED_BUILTIN, LOW);   // turn the LED off (LOW is the voltage level)
    }
  }
  delay(500);
   if(inChar == 'a')
    {
      Serial.write("LED ON");
    }
    else
    {
      Serial.write("LED OFF");
    }
}

错误的最终图像:

TERMINAL WITH ERROR image

请帮忙! 谢谢,

【问题讨论】:

  • 感谢您提供完整且最少的代码来重现您的问题。欢迎使用 Stack Overflow!

标签: c++ qt arduino serial-port


【解决方案1】:

您没有任何数据包化:各个数据块之间没有分隔符 - 除了时间流逝。

  1. 在 Arudino 方面,您应该使用 println 而不是 write,这样每条消息都是一个完整的行。

  2. 在 Qt 端,处理完整的行。在waitForReadyRead 之后,您不能保证从串口获得完整的响应。您可以保证至少有 1 个字节可供读取。那是你问题的根源。注意你是怎么得到LE的,然后你得到了D OFF,紧接着是LED ON。您必须等待数据,直到有完整的行可用。

以下内容应该适用于 Qt 端 - 另请注意,您不需要那么多包含,并且您可以使用 QTextStream 而不是 iostream,以减少您使用的 API 数量。最后,您不需要app.exec,因为您编写了阻塞代码。

// https://github.com/KubaO/stackoverflown/tree/master/questions/arduino-read-40246601
#include <QtSerialPort>
#include <cstdio>

int main(int argc, char *argv[])
{
    QCoreApplication a{argc, argv};
    QTextStream in{stdin};
    QTextStream out{stdout};

    QSerialPort port;
    port.setPortName("COM6");
    port.setBaudRate(9600);
    port.setDataBits(QSerialPort::Data8);
    port.setParity(QSerialPort::NoParity);
    port.setStopBits(QSerialPort::OneStop);
    port.setFlowControl(QSerialPort::NoFlowControl);

    if (!port.open(QSerialPort::ReadWrite)) {
        out << "Error opening serial port: " << port.errorString() << endl;
        return 1;
    }

    while(true)
    {
        out << "> ";
        auto cmd = in.readLine().toLatin1();
        if (cmd.length() < 1)
            continue;

        port.write(cmd);

        while (!port.canReadLine())
            port.waitForReadyRead(-1);

        while (port.canReadLine())
            out << "< " << port.readLine(); // lines are already terminated
    }
}

如果您愿意,您也可以轻松地将其变成 GUI 应用程序,只需几行代码:

#include <QtSerialPort>
#include <QtWidgets>

int main(int argc, char *argv[])
{
    QApplication app{argc, argv};
    QWidget ui;
    QFormLayout layout{&ui};
    QLineEdit portName{"COM6"};
    QTextBrowser term;
    QLineEdit command;
    QPushButton open{"Open"};
    layout.addRow("Port", &portName);
    layout.addRow(&term);
    layout.addRow("Command:", &command);
    layout.addRow(&open);
    ui.show();

    QSerialPort port;
    port.setBaudRate(9600);
    port.setDataBits(QSerialPort::Data8);
    port.setParity(QSerialPort::NoParity);
    port.setStopBits(QSerialPort::OneStop);
    port.setFlowControl(QSerialPort::NoFlowControl);

    QObject::connect(&open, &QPushButton::clicked, &port, [&]{
        port.setPortName(portName.text());
        if (port.open(QSerialPort::ReadWrite)) return;
        term.append(QStringLiteral("* Error opening serial port: %1").arg(port.errorString()));
    });

    QObject::connect(&command, &QLineEdit::returnPressed, &port, [&]{
        term.append(QStringLiteral("> %1").arg(command.text()));
        port.write(command.text().toLatin1());
    });

    QObject::connect(&port, &QIODevice::readyRead, &term, [&]{
        if (!port.canReadLine()) return;
        while (port.canReadLine())
            term.append(QStringLiteral("< %1").arg(QString::fromLatin1(port.readLine())));
    });
    return app.exec();
}

【讨论】:

    【解决方案2】:

    我认为您必须在 QT 上使用 EOL 和回车符。尝试将 Arduino 代码中的 Serial.write 替换为 Serial.println

    【讨论】:

      猜你喜欢
      • 2019-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多