繁体   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