问题描述
我编写了一个简单的程序来使用 Qt(根据 本指南从 Visual Studio 2013 的源代码构建的 5.5 版)a>) 与 Arduino 通信.
I wrote a simple program to use Qt (version 5.5 built from source for Visual Studio 2013 following this guide) to comunicate with Arduino.
这是一个简单的固件,它从串行读取并在 10 秒后打印1":
Here is a simple firmware which read from the serial and after 10 seconds prints "1" back:
void setup() {
Serial.begin(9600); //Open Serial connection for debugging
}
void loop() {
if (Serial.available()) {
char user_input = Serial.read();
if (user_input == '1') {
delay(10000);
Serial.print('1');
}
}
这是 Qt 程序,当我按下开始按钮并继续监听要读取的消息时,它会在串行发送1":
Here is the Qt program which send "1" on serial when I press the start button and keeps listening for messages to read:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#pragma comment(lib, "advapi32")
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
主窗口.h
#pragma once
#include <QMainWindow>
#include "SerialHandler.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow* ui;
SerialHandler serialHandler;
public slots:
void onStart();
};
mainwindow.cpp
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::MainWindow), serialHandler(QString("COM6")) {
ui->setupUi(this);
QObject::connect(ui->startButton, SIGNAL(released()), this, SLOT(onStart()));
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::onStart() {
serialHandler.moveForward();
}
SerialHandler.h
SerialHandler.h
#pragma once
#include <QString>
#include <QtSerialPort>
#include <QtSerialPort/QSerialPort>
class SerialHandler {
public:
SerialHandler(QString& serialName);
~SerialHandler();
void moveForward();
private:
QSerialPort serial;
void writeOnSerial(QByteArray& msg);
private slots:
void handleReadyRead();
};
SerialHandler.cpp
SerialHandler.cpp
#include "SerialHandler.h"
#include <QDebug>
#include <QObject>
SerialHandler::SerialHandler(QString& serialName){
connect(&serial, SIGNAL(readyRead()), this, SLOT(handleReadyRead()));
// Initialize Serial
serial.setPortName(serialName);
if (!serial.setBaudRate(QSerialPort::Baud9600)) {
throw std::runtime_error(QObject::tr("Can't set rate 9600 baud to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()).toStdString());
}
if (!serial.open(QIODevice::ReadWrite)) {
throw std::runtime_error(QObject::tr("Can't open %1, error code %2")
.arg(serial.portName()).arg(serial.error()).toStdString());
}
if (!serial.setDataBits(QSerialPort::Data8)) {
throw std::runtime_error(QObject::tr("Can't set 8 data bits to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()).toStdString());
}
if (!serial.setParity(QSerialPort::NoParity)) {
throw std::runtime_error(QObject::tr("Can't set no patity to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()).toStdString());
}
if (!serial.setStopBits(QSerialPort::OneStop)) {
throw std::runtime_error(QObject::tr("Can't set 1 stop bit to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()).toStdString());
}
if (!serial.setFlowControl(QSerialPort::NoFlowControl)) {
throw std::runtime_error(QObject::tr("Can't set no flow control to port %1, error code %2")
.arg(serial.portName()).arg(serial.error()).toStdString());
}
}
SerialHandler::~SerialHandler(){
if (serial.isOpen()) {
serial.close();
}
}
void SerialHandler::handleReadyRead() {
qDebug() << serial.readAll();
}
void SerialHandler::writeOnSerial(QByteArray& msg) {
if (serial.isOpen() && serial.isWritable()) {
serial.write(msg);
serial.flush();
}
}
void SerialHandler::moveForward(){
QByteArray msg("1");
writeOnSerial(msg);
}
问题出现在 writeOnSerial 方法 (SerialHandler.cpp) 中.对 serial.write() 的调用会触发此错误:
the problem appears in writeOnSerial method (SerialHandler.cpp). The call to serial.write() fires this error:
QObject::startTimer: Timers can only be used with threads started with QThread
1"写入串行并由 arduino 读取,但计算机在 10 秒后从未收到任何回复,readyRead() 信号从未被触发!
the "1" is written on serial and read by the arduino, but the computer never receives anything back after 10 seconds, the readyRead() signal is never fired!
我在这篇文章中看到了同样的错误,但就我而言,exec 循环就在那里!
I saw the same error in this post, but in my case the exec loop is there!
有什么建议吗?
推荐答案
这个最小的测试用例适用于我在 Windows 和 OS X 上的 Arduino,使用最新的 Qt 5.5.
This minimal test case works for me on an Arduino on both Windows and OS X, using latest Qt 5.5.
这种最小化属于您的问题.不需要多个文件(和丢失的 .ui)来演示这种简单的失败.
This kind of minimization is what belongs in your question. Multiple files (and a missing .ui) aren't necessary to demonstrate such simple failures.
// https://github.com/KubaO/stackoverflown/tree/master/questions/miniserial-36431493
#include <QtWidgets>
#include <QtSerialPort>
int main(int argc, char ** argv) {
QApplication app(argc, argv);
QWidget w;
QFormLayout layout(&w);
QPushButton ping("Send");
QTextBrowser output;
layout.addRow(&ping);
layout.addRow(&output);
w.show();
QSerialPort port("COM6");
port.setBaudRate(QSerialPort::Baud9600); // these are guaranteed to return true
port.setDataBits(QSerialPort::Data8);
port.setParity(QSerialPort::NoParity);
port.setStopBits(QSerialPort::OneStop);
port.setFlowControl(QSerialPort::NoFlowControl);
if (!port.open(QIODevice::ReadWrite))
output.append("! Can't open the port :(<br/>");
QObject::connect(&ping, &QPushButton::clicked, &port, [&]{
if (port.isOpen()) {
port.write("1");
output.append("> 1<br/>");
} else
output.append("! Write failed :(<br/>");
});
QObject::connect(&port, &QIODevice::readyRead, &output, [&]{
auto data = port.readAll();
output.append(QStringLiteral("< %1<br/>")
.arg(QString::fromLatin1(data).toHtmlEscaped()));
});
return app.exec();
}
这篇关于QSerial错误与Arduino通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!