簡體   English   中英

Arduino和Qt 5.7之間的雙向串行通信

[英]Double way Serial communication between Arduino and Qt 5.7

我正在嘗試將數據從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. 在Arudino方面,應該使用println而不是write ,以便每條消息都是完整的一行。

  2. 在Qt方面,處理完整的行。 waitForReadyRead之后,不能保證從串行端口獲得完整的響應。 您所保證的是,至少有1個字節可讀取。 那就是問題的根源。 請注意您如何獲得LE ,然后不久之后您立即將D OFFLED ON 您必須等待數據,直到完整行可用。

以下內容應該可以解決Qt問題-還請注意,您不需要那么多的include,並且可以使用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();
}

我認為您必須在QT上使用EOL和Carrige返回字符。 嘗試更換Serial.writeSerial.println在Arduino的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM