串口助手
一、概念
串行接口是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接受的串行数据流转换为并行的数据字符供给CPU的器件。一般完成这种功能的电路,我们称为串行接口电路。串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。
a,波特率:这是一个衡量符号传输速率的参数。指的是信号被调制以后在单位时间内的变化,即单位时间内载波参数变化的次数,如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。一般调制速率大于波特率,比如曼彻斯特编码)。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。
b,数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。
c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
d,奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位为1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
开发平台:win7+VS2015+Qt5.9
知识技能:串口通信、线程
二、主要功能
1、串口之间的字符传输
2、ASCII、HEX不同模式的接受与发送
3、文本的发送与接收(启用线程,防止软件卡顿现象)
4、定时自动发送功能
三、效果图
四、源码
#include "serialport.h" #include <QtWidgets/QApplication> #include <QtCore/QDebug> int main(int argc, char *argv[]) { QApplication a(argc, argv); SerialPort w; w.show(); return a.exec(); }
#ifndef SERIALPORT_H #define SERIALPORT_H #include <QtWidgets/QMainWindow> #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> #include <QFile> #include <QThread> #include "ui_serialport.h" class CThread; class SerialPort : public QMainWindow { Q_OBJECT public: SerialPort(QWidget *parent = 0); ~SerialPort(); void EnablePort(bool flag); char ConvertHexChar(char ch); void String2Hex(QString str, QByteArray &senddata); private slots: void initPort(); void ReseveDate(); void OpenPort(); void AutoSend(); void SendDate(); void OpenFile(); void SaveFile(); void ShowTime(); void ClearSendDate(); void ClearReceveDate(); void slotFinshFilesend(); private: Ui::SerialPortClass *ui; QSerialPort *m_ComPort; QTimer *m_timer; bool m_isHexSend; CThread *m_thread; }; //线程示例 class CThread : public QThread { Q_OBJECT public: CThread(QSerialPort *serialPort, QString filepath); protected: void run(); void sendFile(); private: QString m_filePath; QSerialPort *m_serialPort; signals: void changeProgressValue(int value); }; #endif // SERIALPORT_H
#include "serialport.h" #include <QTimer> #include <QMessageBox> #include <QFileDialog> #include <windows.h> SerialPort::SerialPort(QWidget *parent) : QMainWindow(parent), ui(new Ui::SerialPortClass) { ui->setupUi(this); setWindowTitle(QString::fromLocal8Bit("串口助手")); //查找可用的串口 foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { QSerialPort serial; serial.setPort(info); if (serial.open(QIODevice::ReadWrite)) { ui->m_ComNumber->addItem(serial.portName()); serial.close(); } } ui->m_Send->setEnabled(false); //关联各种槽函数 connect(ui->m_AutoSend, SIGNAL(stateChanged(int)), this, SLOT(AutoSend())); connect(ui->m_OnOff, SIGNAL(clicked()), this, SLOT(OpenPort())); connect(ui->m_Send, SIGNAL(clicked()), this, SLOT(SendDate())); connect(ui->m_RxClear, SIGNAL(clicked()), this, SLOT(ClearReceveDate())); connect(ui->m_TxClear, SIGNAL(clicked()), this, SLOT(ClearSendDate())); connect(ui->m_TxFile, SIGNAL(clicked()), this, SLOT(OpenFile())); connect(ui->m_RxFile, SIGNAL(clicked()), this, SLOT(SaveFile())); //设置定时器 m_timer = new QTimer(); //选中自动发送,每隔一段时间就发送一次 connect(m_timer, SIGNAL(timeout()), this, SLOT(AutoSend())); //m_timer->start(1000); } SerialPort::~SerialPort() { delete ui; } //使能串口的各项参数 void SerialPort::EnablePort(bool flag) { ui->m_ComNumber->setEnabled(flag); ui->m_BaudRate->setEnabled(flag); ui->m_CheckBit->setEnabled(flag); ui->m_DataBits->setEnabled(flag); ui->m_StopBit->setEnabled(flag); ui->m_FluidControl->setEnabled(flag); } //初始化串口 void SerialPort::initPort() { //设置串口号 m_ComPort->setPortName(ui->m_ComNumber->currentText()); //设置波特率 m_ComPort->setBaudRate(ui->m_BaudRate->currentText().toInt()); //设置数据位 switch (ui->m_DataBits->currentIndex()) { case 0: m_ComPort->setDataBits(QSerialPort::Data5); break; case 1: m_ComPort->setDataBits(QSerialPort::Data6); break; case 2: m_ComPort->setDataBits(QSerialPort::Data7); break; case 3: m_ComPort->setDataBits(QSerialPort::Data8); break; } //设置校验位 switch (ui->m_CheckBit->currentIndex()) { case 0: m_ComPort->setParity(QSerialPort::NoParity); break; case 1: m_ComPort->setParity(QSerialPort::OddParity); break; case 2: m_ComPort->setParity(QSerialPort::EvenParity); break; default: m_ComPort->setParity(QSerialPort::MarkParity); break; } //设置停止位 switch (ui->m_StopBit->currentIndex()) { case 0: m_ComPort->setStopBits(QSerialPort::OneStop); break; case 1: m_ComPort->setStopBits(QSerialPort::OneAndHalfStop); break; default: m_ComPort->setStopBits(QSerialPort::TwoStop); break; } //设置流控制 switch (ui->m_FluidControl->currentIndex()) { case 0: m_ComPort->setFlowControl(QSerialPort::NoFlowControl); break; case 1: m_ComPort->setFlowControl(QSerialPort::HardwareControl); break; case 2: m_ComPort->setFlowControl(QSerialPort::SoftwareControl); break; default: m_ComPort->setFlowControl(QSerialPort::UnknownFlowControl); break; } } //打开或关闭串口 void SerialPort::OpenPort() { if (ui->m_OnOff->text() == QString::fromLocal8Bit("打开")) { m_ComPort = new QSerialPort(this); //m_ComPort = new QSerialPort; initPort(); if (m_ComPort->open(QIODevice::ReadWrite)) { //连接信号槽 connect(m_ComPort, SIGNAL(readyRead()), this, SLOT(ReseveDate())); /* QObject::connect(m_ComPort, &QSerialPort::readyRead, this, &SerialPort::ReseveDate);*/ ui->m_Send->setEnabled(true); EnablePort(false); ui->m_OnOff->setText(QString::fromLocal8Bit("关闭")); QMessageBox::information(this, tr("Connect Device"), tr("Open com port connect success!")); } else { QMessageBox::information(this, tr("Connect Device"), tr("Open com port connect fail!")); return; } } else { //关闭串口 m_ComPort->clear(); m_ComPort->close(); m_ComPort->deleteLater(); ui->m_Send->setEnabled(false); EnablePort(true); ui->m_OnOff->setText(QString::fromLocal8Bit("打开")); } } //自动发送函数 void SerialPort::AutoSend() { if (ui->m_AutoSend->isChecked()) { int times = ui->m_time->text().toInt(); if (times!=0) { m_timer->start(times*1000); SendDate(); } } else { if (m_timer->isActive()) m_timer->stop(); } } //发送数据 void SerialPort::SendDate() { QString sdata; sdata = ui->m_EditText->toPlainText(); if (sdata.isEmpty()) return; QByteArray sendBuf; if (ui->m_TxHEX->isChecked()) m_isHexSend = true; else m_isHexSend = false; if (m_isHexSend) { //sendBuf = QByteArray::fromHex(sdata.toLatin1());//返回16进制编码的副本 int len = sdata.length(); if (len % 2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0 { sdata = sdata.insert(len - 1, '0'); //insert(int position, const QString & str) } String2Hex(sdata, sendBuf); } else { sendBuf = sdata.toUtf8(); //sendBuf = sdata.toLatin1(); } m_ComPort->write(sendBuf); } //读取数据 void SerialPort::ReseveDate() { //读取串口数据 QByteArray byte_data = m_ComPort->readAll(); //将读取到的数据进行转化 QString strDisplay; //判断显示模式 if (ui->m_RxHEX->isChecked()) m_isHexSend = true; else m_isHexSend = false; //是否是按16进制显示 if (m_isHexSend) { QDataStream out(&byte_data, QIODevice::ReadWrite); while (!out.atEnd()) { qint8 outChar = 0; out >> outChar; QString str = QString("%1").arg(outChar & 0xFF, 2, 16, QLatin1Char('0')).toUpper() + QString(tr(" ")); strDisplay += str; } ui->m_ShowText->insertPlainText(strDisplay); } else { ui->m_ShowText->append(byte_data); } } //选择文件发送 void SerialPort::OpenFile() { QString filename = QFileDialog::getOpenFileName(this, "please select send file", ".", tr("Text files(*.bin)")); if (filename.isEmpty()) { return; } m_thread = new CThread(m_ComPort,filename); m_thread->start(); connect(m_thread, SIGNAL(finished()), this, SLOT(slotFinshFilesend())); } //将接收到的数据保存为文件 void SerialPort::SaveFile() { QString text = ui->m_ShowText->toPlainText(); if (text == "") { QMessageBox::warning(this, tr("warning"), tr("there are no text!")); return; } QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "./save.bin", tr("Text files (*.bin)")); QFile file(fileName); if (file.open((QIODevice::WriteOnly))) { QDataStream in(&file); in << text; } } void SerialPort::ShowTime() { } //清空发送框数据 void SerialPort::ClearSendDate() { ui->m_EditText->setText(tr("")); } //清空接收框数据 void SerialPort::ClearReceveDate() { ui->m_ShowText->setText(tr("")); } //将string类型转Hex格式 void SerialPort::String2Hex(QString str, QByteArray &senddata) { int hexdata, lowhexdata; int hexdatalen = 0; int len = str.length(); senddata.resize(len / 2); char lstr, hstr; for (int i = 0; i < len; ) { //char lstr, hstr = str[i].toLatin1(); if (hstr == ' ') { i++; continue; } i++; if (i >= len) break; lstr = str[i].toLatin1(); hexdata = ConvertHexChar(hstr); lowhexdata = ConvertHexChar(lstr); if ((hexdata == 16) || (lowhexdata == 16)) break; else hexdata = hexdata * 16 + lowhexdata; i++; senddata[hexdatalen] = (char)hexdata; hexdatalen++; } senddata.resize(hexdatalen); } //char转ASCII char SerialPort::ConvertHexChar(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - 0x30; else if ((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10; else if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; else return (-1); } //完成文本数据发送提示框 void SerialPort::slotFinshFilesend() { QMessageBox::information(this, tr("Send File"), tr("send file success!")); delete m_thread; } //线程,用一个线程来发送.bin文件,主要用于解决当文本比较大的时候软件出现卡顿的情况 CThread::CThread(QSerialPort *serialPort,QString filepath) { m_serialPort = serialPort; m_filePath = filepath; } void CThread::run() { /*mutex.lock();*/ sendFile(); /*mutex.unlock();*/ } void CThread::sendFile() { QFile file(m_filePath); if (file.open(QIODevice::ReadOnly)) { QDataStream in(&file); char buf[1024]; int count = 0; while (!in.atEnd()) { count = in.readRawData(buf, 1024); m_serialPort->write(buf, count); while (m_serialPort->waitForBytesWritten()) { Sleep(5); } } } }
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>SerialPortClass</class> <widget class="QMainWindow" name="SerialPortClass"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>665</width> <height>501</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="windowTitle"> <string>SerialPort</string> </property> <widget class="QWidget" name="centralWidget"> <layout class="QGridLayout" name="gridLayout_6"> <item row="0" column="0"> <layout class="QGridLayout" name="gridLayout_5"> <item row="0" column="1"> <layout class="QGridLayout" name="gridLayout_2"> <item row="2" column="1"> <widget class="QPushButton" name="m_OnOff"> <property name="text"> <string>打开</string> </property> </widget> </item> <item row="2" column="0" rowspan="2"> <widget class="QTextEdit" name="m_EditText"/> </item> <item row="0" column="0" colspan="2"> <widget class="QTextEdit" name="m_ShowText"/> </item> <item row="1" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeType"> <enum>QSizePolicy::Maximum</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>13</height> </size> </property> </spacer> </item> <item row="3" column="1"> <widget class="QPushButton" name="m_Send"> <property name="text"> <string>发送</string> </property> </widget> </item> </layout> </item> <item row="0" column="0"> <widget class="QGroupBox" name="groupBox_4"> <property name="minimumSize"> <size> <width>190</width> <height>0</height> </size> </property> <property name="title"> <string/> </property> <widget class="QGroupBox" name="groupBox"> <property name="geometry"> <rect> <x>0</x> <y>10</y> <width>181</width> <height>201</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="title"> <string>串口设置</string> </property> <widget class="QWidget" name="layoutWidget"> <property name="geometry"> <rect> <x>12</x> <y>20</y> <width>161</width> <height>171</height> </rect> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="text"> <string>端 口:</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QComboBox" name="m_ComNumber"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> <string>波特率:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QComboBox" name="m_BaudRate"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <item> <property name="text"> <string>9600</string> </property> </item> <item> <property name="text"> <string>19200</string> </property> </item> <item> <property name="text"> <string>38400</string> </property> </item> <item> <property name="text"> <string>57600</string> </property> </item> <item> <property name="text"> <string>115200</string> </property> </item> <item> <property name="text"> <string>Custom</string> </property> </item> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>数据位:</string> </property> </widget> </item> <item row="2" column="1"> <widget class="QComboBox" name="m_DataBits"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <item> <property name="text"> <string>5</string> </property> </item> <item> <property name="text"> <string>6</string> </property> </item> <item> <property name="text"> <string>7</string> </property> </item> <item> <property name="text"> <string>8</string> </property> </item> </widget> </item> <item row="3" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>校验位:</string> </property> </widget> </item> <item row="3" column="1"> <widget class="QComboBox" name="m_CheckBit"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <item> <property name="text"> <string>None</string> </property> </item> <item> <property name="text"> <string>Odd</string> </property> </item> <item> <property name="text"> <string>Even</string> </property> </item> </widget> </item> <item row="4" column="0"> <widget class="QLabel" name="label_5"> <property name="text"> <string>停止位:</string> </property> </widget> </item> <item row="4" column="1"> <widget class="QComboBox" name="m_StopBit"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <item> <property name="text"> <string>1</string> </property> </item> <item> <property name="text"> <string>1.5</string> </property> </item> <item> <property name="text"> <string>2</string> </property> </item> </widget> </item> <item row="5" column="0"> <widget class="QLabel" name="label_6"> <property name="text"> <string>流 控:</string> </property> </widget> </item> <item row="5" column="1"> <widget class="QComboBox" name="m_FluidControl"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <item> <property name="text"> <string>None</string> </property> </item> <item> <property name="text"> <string>RTX/CTS</string> </property> </item> <item> <property name="text"> <string>XON/XOFF</string> </property> </item> </widget> </item> </layout> </widget> </widget> <widget class="QGroupBox" name="groupBox_3"> <property name="geometry"> <rect> <x>0</x> <y>220</y> <width>181</width> <height>101</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="title"> <string>接收设置</string> </property> <widget class="QWidget" name="layoutWidget"> <property name="geometry"> <rect> <x>11</x> <y>20</y> <width>159</width> <height>73</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QRadioButton" name="m_RxASCII"> <property name="text"> <string>ASCII</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item row="0" column="1" colspan="2"> <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item row="0" column="3"> <widget class="QRadioButton" name="m_RxHEX"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> <string>HEX</string> </property> </widget> </item> <item row="1" column="0" colspan="2"> <widget class="QCheckBox" name="m_ShowTime"> <property name="text"> <string>显示时间</string> </property> </widget> </item> <item row="2" column="0" colspan="2"> <widget class="QPushButton" name="m_RxFile"> <property name="text"> <string>保存为文件</string> </property> </widget> </item> <item row="2" column="2" colspan="2"> <widget class="QPushButton" name="m_RxClear"> <property name="text"> <string>清空接收</string> </property> </widget> </item> </layout> </widget> </widget> <widget class="QGroupBox" name="groupBox_2"> <property name="geometry"> <rect> <x>0</x> <y>330</y> <width>181</width> <height>111</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="title"> <string>发送设置</string> </property> <widget class="QWidget" name="layoutWidget"> <property name="geometry"> <rect> <x>11</x> <y>20</y> <width>159</width> <height>77</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_4"> <item row="0" column="0"> <widget class="QRadioButton" name="m_TxASCII"> <property name="text"> <string>ASCII</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> <item row="0" column="1" colspan="2"> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item row="0" column="3" colspan="2"> <widget class="QRadioButton" name="m_TxHEX"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>10</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="text"> <string>HEX</string> </property> </widget> </item> <item row="1" column="0" colspan="2"> <widget class="QCheckBox" name="m_AutoSend"> <property name="text"> <string>自动发送</string> </property> </widget> </item> <item row="1" column="2" colspan="2"> <widget class="QSpinBox" name="m_time"> <property name="sizePolicy"> <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="maximumSize"> <size> <width>50</width> <height>20</height> </size> </property> <property name="value"> <number>1</number> </property> </widget> </item> <item row="1" column="4"> <widget class="QLabel" name="label_7"> <property name="text"> <string>秒</string> </property> </widget> </item> <item row="2" column="0" colspan="2"> <widget class="QPushButton" name="m_TxFile"> <property name="text"> <string>发送文件</string> </property> </widget> </item> <item row="2" column="2" colspan="3"> <widget class="QPushButton" name="m_TxClear"> <property name="text"> <string>清空发送</string> </property> </widget> </item> </layout> </widget> </widget> </widget> </item> </layout> </item> </layout> </widget> <widget class="QMenuBar" name="menuBar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>665</width> <height>21</height> </rect> </property> </widget> <widget class="QToolBar" name="mainToolBar"> <attribute name="toolBarArea"> <enum>TopToolBarArea</enum> </attribute> <attribute name="toolBarBreak"> <bool>false</bool> </attribute> </widget> <widget class="QStatusBar" name="statusBar"/> </widget> <layoutdefault spacing="6" margin="11"/> <resources> <include location="serialport.qrc"/> </resources> <connections/> </ui>