【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口

之前有一篇文章讲过驱动到应用串口部分,之前的算是控制台篇,本章将主要围绕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转串口调试

【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口_第1张图片

设备树配置(之前有提过,这里简述)

//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编译文件系统即可

【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口_第2张图片

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显示效果如下(可正常使用):

【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口_第3张图片

windows UI 显示效果如下(可正常使用):

【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口_第4张图片

交叉编译输出适合arm的执行文件,将执行文件拷贝到开发板文件系统,启动开发板执行可执行文件,测试收发情况(注意打开ttymxc2对应开发板串口3):

【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口_第5张图片

【IMX6ULL笔记】-- 从驱动到应用(基于Qt)- 串口_第6张图片

你可能感兴趣的:(imx6ull,qt,Linux,qt,开发语言,arm)