之前有一篇文章讲过驱动到应用串口部分,之前的算是控制台篇,本章将主要围绕Qt搭建界面交互的串口
uart 驱动到应用
1.imx6ull 开发板(笔者使用的是 韦东山开发板)
2.内核版本 4.9.88
3.文件系统(buildroot 2019.02工具输出)移植好qt
4.ubuntu 安装好qt
5.交叉编译工具链:gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf
原理图,因为串口3被 485占用,我们向此处飞线接上USB转串口调试
设备树配置(之前有提过,这里简述)
//pinctrl 配置如下
pinctrl_uart3: uart3grp {
fsl,pins = <
MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX 0X1b0b1
MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX 0X1b0b1
>;
};
//节点配置如下,基本就是把 imx6ull.dtsi 文件中,uart3节点再重新配置一遍
//可以把 imx6ull.dtsi 当作默认配置文件
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
status = "okay";
};
修改完成,编译,替换新的dtb文件
make dtbs
使用buildroot qt中添加qt5serialport,然后重新make编译文件系统即可
QT工程搭建
*.pro文件中注意添加 serialport
QT += core gui serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
源码如下(这种代码网上也一大把,可以拉下来根据项目作一定修改):
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QSerialPort *pSerialPort;
/************左边布局************/
QGridLayout* pLeftLayout;
QLabel* pLabel[5];
QComboBox* pComboBox[5];
QPushButton *pPushButton[3];
/************右边布局************/
QVBoxLayout* pRightLayout;
QTextBrowser *pTextRecive;
QTextEdit *pTextSend;
/************主体布局************/
QWidget* mainWidget;
QHBoxLayout* pMainWidget;
private:
void layoutConfig(void);
void scanSerialPort(void);
void baudRateInit(void);
void dataBitsInit(void);
void parityInit(void);
void stopBitsInit(void);
private slots:
void sendSerialPortData();
void openSerialPortDevice();
void clearTextData();
void serialPortReadyRead();
};
#endif // MAINWINDOW_H
.......
#include "mainwindow.h"
#include
#include
#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
layoutConfig();
scanSerialPort();
baudRateInit();
dataBitsInit();
parityInit();
stopBitsInit();
}
MainWindow::~MainWindow()
{
}
//
void MainWindow::layoutConfig(void)
{
QList <QScreen *> list_screen = QGuiApplication::screens();
/* 如果是ARM平台,直接设置大小为屏幕的大小 */
#if __arm__
/* 重设大小 */
this->resize(list_screen.at(0)->geometry().width(),
list_screen.at(0)->geometry().height());
#else
this->resize(800, 480);
#endif
setWindowTitle("serialport");
int i;
/****************左边布局***************/
pLeftLayout = new QGridLayout();
/* QList链表,字符串类型 */
QList <QString> list1;
list1<<"端口:"<<"波特率:"<<"数据位:"<<"停止位:"<<"校验:";
for(i=0;i<5;i++)
{
pLabel[i] = new QLabel(list1[i]);
pComboBox[i] = new QComboBox();
pLeftLayout->addWidget(pLabel[i],i,0);
pLeftLayout->addWidget(pComboBox[i],i,1);
}
pPushButton[0] = new QPushButton("打开串口");
pPushButton[1] = new QPushButton("发送");
pPushButton[2] = new QPushButton("清空数据");
pPushButton[1]->setEnabled(false);
pLeftLayout->addWidget(pPushButton[0],5,0,1,2);
pLeftLayout->addWidget(pPushButton[1],6,0,1,2);
pLeftLayout->addWidget(pPushButton[2],7,0,1,2);
pLeftLayout->setColumnStretch(0,1);
pLeftLayout->setColumnStretch(1,3);
/****************右边布局***************/
pRightLayout = new QVBoxLayout();
pTextRecive = new QTextBrowser();
pTextSend = new QTextEdit();
pRightLayout->addWidget(pTextRecive);
pRightLayout->addWidget(pTextSend);
/****************主体布局***************/
QHBoxLayout* pMainWidget;
pMainWidget = new QHBoxLayout();
pMainWidget->addLayout(pLeftLayout);
pMainWidget->addLayout(pRightLayout);
pMainWidget->setStretch(0,1);
pMainWidget->setStretch(1,4);
mainWidget = new QWidget();
mainWidget->setLayout(pMainWidget);
this->setCentralWidget(mainWidget);
/* 信号槽连接 */
connect(pPushButton[0], SIGNAL(clicked()),
this, SLOT(openSerialPortDevice()));
connect(pPushButton[1], SIGNAL(clicked()),
this, SLOT(sendSerialPortData()));
connect(pPushButton[2], SIGNAL(clicked()),
this, SLOT(clearTextData()));
}
void MainWindow::scanSerialPort(void)
{
pSerialPort = new QSerialPort(this);
connect(pSerialPort, SIGNAL(readyRead()),
this, SLOT(serialPortReadyRead()));
/* 查找可用串口 */
foreach (const QSerialPortInfo &info,
QSerialPortInfo::availablePorts())
{
pComboBox[0]->addItem(info.portName());
}
}
void MainWindow::baudRateInit(void)
{
int i;
QList <QString> list;
list<<"1200"<<"2400"<<"4800"<<"9600"
<<"19200"<<"38400"<<"57600"
<<"115200"<<"230400"<<"460800"
<<"921600";
for (i = 0; i < 11; i++)
{
pComboBox[1]->addItem(list[i]);
}
pComboBox[1]->setCurrentIndex(7);
}
void MainWindow::dataBitsInit(void)
{
int i;
QList <QString> list;
list<<"5"<<"6"<<"7"<<"8";
for (i = 0; i < 4; i++)
{
pComboBox[2]->addItem(list[i]);
}
pComboBox[2]->setCurrentIndex(3);
}
void MainWindow::parityInit(void)
{
int i;
QList <QString> list;
list<<"None"<<"Even"<<"Odd"<<"Space"<<"Mark";
for (i = 0; i < 5; i++)
{
pComboBox[3]->addItem(list[i]);
}
pComboBox[3]->setCurrentIndex(0);
}
void MainWindow::stopBitsInit(void)
{
int i;
QList <QString> list;
list<<"1"<<"2";
for (i = 0; i < 2; i++)
{
pComboBox[4]->addItem(list[i]);
}
pComboBox[4]->setCurrentIndex(0);
}
void MainWindow::sendSerialPortData()
{
/* 获取textEdit数据,转换成utf8格式的字节流 */
QByteArray data = pTextSend->toPlainText().toUtf8();
pSerialPort->write(data);
}
void MainWindow::openSerialPortDevice()
{
int i;
if (pPushButton[0]->text() == "打开串口")
{
/* 设置串口名 */
pSerialPort->setPortName(pComboBox[0]->currentText());
/* 设置波特率 */
pSerialPort->setBaudRate(pComboBox[1]->currentText().toInt());
/* 设置数据位数 */
switch (pComboBox[2]->currentText().toInt())
{
case 5:
pSerialPort->setDataBits(QSerialPort::Data5);
break;
case 6:
pSerialPort->setDataBits(QSerialPort::Data6);
break;
case 7:
pSerialPort->setDataBits(QSerialPort::Data7);
break;
case 8:
pSerialPort->setDataBits(QSerialPort::Data8);
break;
default: break;
}
/* 设置奇偶校验 */
switch (pComboBox[3]->currentIndex())
{
case 0:
pSerialPort->setParity(QSerialPort::NoParity);
break;
case 1:
pSerialPort->setParity(QSerialPort::EvenParity);
break;
case 2:
pSerialPort->setParity(QSerialPort::OddParity);
break;
case 3:
pSerialPort->setParity(QSerialPort::SpaceParity);
break;
case 4:
pSerialPort->setParity(QSerialPort::MarkParity);
break;
default: break;
}
/* 设置停止位 */
switch (pComboBox[4]->currentText().toInt())
{
case 1:
pSerialPort->setStopBits(QSerialPort::OneStop);
break;
case 2:
pSerialPort->setStopBits(QSerialPort::TwoStop);
break;
default: break;
}
/* 设置流控制 */
pSerialPort->setFlowControl(QSerialPort::NoFlowControl);
if (!pSerialPort->open(QIODevice::ReadWrite))
QMessageBox::about(NULL, "错误",
"串口无法打开!可能串口已经被占用!");
else
{
for (i = 0; i < 5; i++)
{
pComboBox[i]->setEnabled(false);
}
pPushButton[0]->setText("关闭串口");
pPushButton[1]->setEnabled(true);
}
}
else
{
pSerialPort->close();
for (i = 0; i < 5; i++)
{
pComboBox[i]->setEnabled(true);
}
pPushButton[0]->setText("打开串口");
pPushButton[1]->setEnabled(false);
}
}
void MainWindow::clearTextData(void)
{
pTextRecive->clearHistory();
pTextSend->clear();
}
void MainWindow::serialPortReadyRead()
{
/* 接收缓冲区中读取数据 */
QByteArray buf = pSerialPort->readAll();
pTextRecive->insertPlainText(QString(buf));
}
ubuntu UI显示效果如下(可正常使用):
windows UI 显示效果如下(可正常使用):
交叉编译输出适合arm的执行文件,将执行文件拷贝到开发板文件系统,启动开发板执行可执行文件,测试收发情况(注意打开ttymxc2对应开发板串口3):