Qt6.2.4 Arduino 上位机

参考

环境

环境 版本
windows 10
Qt 6.2.4
Qt Creator 8.0.1 (Community)
qmake

软件截图

下载地址:https://files.cnblogs.com/files/xiaqiuchu/ArduinoBaud.7z?t=1664421806

image

注意

可以修改为你定义的行尾结束符。

因为输出是连续的,不是一次性读取到全部数据,所以当前行尾结束符定义为 \n,所以下位机需要通过 Serial.println 输出 Qt才能判断读到了一行数据。

代码

上位机代码(QT)

main.h

#include "mainwindow.h"

#include <QApplication>
// 参考:https://zhuanlan.zhihu.com/p/507277665
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QString>
#include <QIODeviceBase>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_portPushButton_clicked();

    void on_openSerialPortPushButton_clicked();

    void on_closeSerialPortPushButton_clicked();

    void on_portComboBox_currentTextChanged(const QString &arg1);

    void on_baudComboBox_currentTextChanged(const QString &arg1);

    void on_sendDataPushButton_clicked();

    void receiveInfo();

    void on_endTagLineEdit_textChanged(const QString &arg1);

private:
    Ui::MainWindow *ui;
    QSerialPort *serialPort;
    void loadPorts();
    void loadBauds();
    QString readData;
    void openSerialPort();
    void onChangePortStatus(bool status);
    QString endTag;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QMessageBox>
#include <QRegularExpression>
#include <QByteArray>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    /* 创建一个串口对象 */
    serialPort = new QSerialPort(this);
    connect(serialPort,SIGNAL(readyRead()),this,SLOT(receiveInfo()));
    // 初始化串口状态
    this->onChangePortStatus(false);
    //
    this->loadPorts();
    this->loadBauds();
}

MainWindow::~MainWindow()
{
    delete ui;
}
/**
 * @brief MainWindow::loadPorts
 * 加载串口列表
 */
void MainWindow::loadPorts()
{
    QStringList serialNamePort;
    ui->portComboBox->clear();
    /* 搜索所有可用串口 */
    foreach (const QSerialPortInfo &inf0, QSerialPortInfo::availablePorts()) {
        serialNamePort<<inf0.portName();
    }
    ui->portComboBox->addItems(serialNamePort);
}

void MainWindow::loadBauds()
{
    ui->baudComboBox->clear();
    QStringList bauds;
    bauds << "9600" << "19200";
    ui->baudComboBox->addItems(bauds);
}
/**
 * @brief MainWindow::openSerialPort
 * 打开串口
 */
void MainWindow::openSerialPort()
{
    /* 串口设置 */
    serialPort->setPortName(ui->portComboBox->currentText());
    serialPort->setBaudRate(ui->baudComboBox->currentText().toInt());
    serialPort->setDataBits(QSerialPort::Data8);
    serialPort->setStopBits(QSerialPort::OneStop);
    serialPort->setParity(QSerialPort::NoParity);
    /* 打开串口提示框 */
    QString consoleStr;
    bool openStatus = serialPort->open(QIODevice::ReadWrite);
    // 更新按钮串口状态
    this->onChangePortStatus(openStatus);
    //
    if (true == openStatus)
    {
        consoleStr = "Open Success port : "+ui->portComboBox->currentText()+" ; baud : "+ui->baudComboBox->currentText();
    }
    else
    {
        consoleStr = "Open Error msg: "+serialPort->errorString();
    }

    ui->consoleTextEdit->append(consoleStr);
}
/**
 * @brief MainWindow::onChangePortStatus
 * @param status
 * 修改串口状态
 */
void MainWindow::onChangePortStatus(bool status)
{
    ui->openSerialPortPushButton->setDisabled(status);
    ui->closeSerialPortPushButton->setDisabled(!status);
    ui->sendDataPushButton->setDisabled(!status);
}

void MainWindow::on_portPushButton_clicked()
{
    this->loadPorts();
}


void MainWindow::on_openSerialPortPushButton_clicked()
{
    this->openSerialPort();
}


void MainWindow::on_closeSerialPortPushButton_clicked()
{
    if(serialPort->isOpen()){
        serialPort->close();
        ui->consoleTextEdit->append("Close Success");
    }else{
        ui->consoleTextEdit->append("Close Error : device not open");
    }

    this->onChangePortStatus(false);
}


void MainWindow::on_portComboBox_currentTextChanged(const QString &arg1)
{
    qDebug() << arg1;
}


void MainWindow::on_baudComboBox_currentTextChanged(const QString &arg1)
{
    qDebug() << arg1;
}


void MainWindow::on_sendDataPushButton_clicked()
{
    QString sendData = ui->dataLineEdit->text();
    ui->consoleTextEdit->append("Send Data : "+sendData);
    ui->dataLineEdit->setText("");

    if(serialPort->write(sendData.toUtf8()) == -1){
        ui->consoleTextEdit->append("Error : device not open");
        this->onChangePortStatus(false);
    }

}

void MainWindow::receiveInfo()
{
    QString info = serialPort->readAll();
    qDebug() << info;
    readData.append(info);
    if(info.endsWith("\n")){
        qDebug() << readData;
        // https://blog.csdn.net/weixin_43491568/article/details/102959168
        ui->consoleTextEdit->append("Read Data : "+ readData.simplified());
        readData = "";
    }
}


void MainWindow::on_endTagLineEdit_textChanged(const QString &arg1)
{
    endTag = arg1;
}


mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>590</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QHBoxLayout" name="horizontalLayout_2">
    <item>
     <layout class="QVBoxLayout" name="verticalLayout_2">
      <item>
       <widget class="QLabel" name="label_4">
        <property name="text">
         <string>串口日志</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QTextEdit" name="consoleTextEdit"/>
      </item>
     </layout>
    </item>
    <item>
     <layout class="QVBoxLayout" name="verticalLayout">
      <property name="sizeConstraint">
       <enum>QLayout::SetDefaultConstraint</enum>
      </property>
      <item>
       <widget class="QLabel" name="label">
        <property name="text">
         <string>串口</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QComboBox" name="portComboBox"/>
      </item>
      <item>
       <widget class="QPushButton" name="portPushButton">
        <property name="text">
         <string>刷新</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QLabel" name="label_2">
        <property name="text">
         <string>波特率</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QComboBox" name="baudComboBox"/>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <widget class="QPushButton" name="openSerialPortPushButton">
          <property name="text">
           <string>打开串口</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QPushButton" name="closeSerialPortPushButton">
          <property name="text">
           <string>关闭串口</string>
          </property>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <widget class="QLabel" name="label_5">
        <property name="text">
         <string>行尾结束符(接收到结束符代表一行)</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QLineEdit" name="endTagLineEdit">
        <property name="enabled">
         <bool>false</bool>
        </property>
        <property name="text">
         <string>\n</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QLabel" name="label_3">
        <property name="text">
         <string>输入数据</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QLineEdit" name="dataLineEdit"/>
      </item>
      <item>
       <widget class="QPushButton" name="sendDataPushButton">
        <property name="text">
         <string>发送数据</string>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="verticalSpacer">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>40</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>590</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

下位机代码(Arduino)

arduino.ino


String readAllPort(){
  String comdata = "";
  while (Serial.available() > 0){
      comdata += char(Serial.read());  //每次读一个char字符,并相加
      delay(2);
  }
  return comdata;
}

void setup()
{
    Serial.begin(9600);
    Serial.println("start arduino");
}
 
void loop()
{
    String comdata = readAllPort();
    if (comdata.length() > 0){
        Serial.println("received:"+comdata); //打印接收到的字符
        // Serial.print("received:"+comdata);
        comdata = "";
    }
}


posted @   夏秋初  阅读(389)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示