Arduino和Qt 5.7之间的双向串行通信

4

我正在尝试将数据从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");
    }
}

错误的终端截图:

带有错误的终端截图

请帮忙!

谢谢,


1
感谢您提供了完整且最简化的代码来复制您的问题。欢迎来到Stack Overflow! - Kuba hasn't forgotten Monica
2个回答

5
您没有任何分组:除了时间流逝之外,单个数据块之间没有分隔符。
1. 在Arduino端,您应该使用println而不是write,以便每个消息都是完整的一行。
2. 在Qt端,处理完整的行。您不能保证在waitForReadyRead之后从串口获得完整的响应。你只能保证至少有1个字节可读。这就是你的问题所在。注意你先得到了LE,然后过了一段时间,你立即得到了D OFFLED 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();
}

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接