3. 窗口代码化设计–串口通信

前面了解了使用Qt Designer进行可视化UI设计,接下来看下窗口代码化设计,用纯代码进行窗口的设计和布局。

我们将纯代码设计一个简单串口通信的窗口,显示串口的接收和发送。

提示

本章的串口例程只是了解下纯代码窗口设计,没有使用Qt的串口模块QtSerialPort,QtSerialPort模块的使用参考下后面章节。

3.1. 鲁班猫板卡串口资源介绍

鲁班猫板卡上,普通IO口可以复用为串口,以LubanCat2板卡为例( 其他鲁班猫系列板卡引脚参考 https://doc.embedfire.com/linux/rk356x/quick_start/zh/latest/quick_start/40pin/40pin.html

gpio01.png

看到上面图片中红色框框的部分,引出的40 Pin中,最多可以复用出5个串口(UART3、UART4、UART7、UART8、UART9)。 开启串口的复用,需要修改下/boot/uEnv/uEnvLubanCat2.txt文件(这里是以LubanCat2为例,其他鲁班猫板卡的类似,比如LubanCat1,就是修改/boot/uEnv/uEnvLubanCat1.txt文件)。

我们测试下LubanCat2板卡的串口3,需要开启下串口,在板卡终端使用命令,然后修改:

cat@lubancat:~$ sudo vim /boot/uEnv/uEnvLubanCat2.txt
gpio01.png

重启后就可以看到:

cat@lubancat:~$ ls /dev/ttyS*
/dev/ttyS3

# /dev/ttyS3就是uart3的设备文件

串口的开启也可以使用我们提供的fire-config工具, 更多串口的开启和测试看下 这里

3.2. 串口例程

3.2.1. 编程思路

我们要实现一个简单的串口通信例程,是板卡和PC上位机通过usb转串口线通信。板卡串口的使用通过基本的系统调用,使用open函数打开串口设备文件,tcsetattr函数设置基础的串口参数,还有ioctl等等。 在这个示例中,串口参数我们默认使用 115200-N-8-1

  • 使用Qt Creator创建一个qt_serial工程(基于qwidget),不勾选使用form UI;

  • 设计一个简单串口通信的窗口,创建一个1个显示框(QTextEdit),1个输入框(QLineEdit),1个按键等;

  • 向工程中添加一个串口类(Uart),实现串口的打开,关闭,发送,接收等基础操作;

  • 在Widget文件,初始化窗口,开启串口,关联信号与槽,在主函数显示窗口。

3.2.2. 创建工程文件

参考前面第一章教程,创建一个qt_serial工程,注意不勾选使用form:

gpio01.png

然后一路点击,就完成了工程的创建。

3.2.3. 界面设计和布局

在widget.h中,声明一些函数等:

lubancat_qt_tutorial_code/QtSerial/widget.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QListWidget>
#include <QGridLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QLineEdit>
#include <QTimer>

#include "uart.h"

class Widget : public QWidget
{
   Q_OBJECT

public:
   Uart uart3;            //串口
   void iniUI();          //初始化窗口

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

private:
   QTextEdit *textEdit;   //用于显示信息
   QLineEdit *lineEdit;   //用于输入
   QPushButton *BtnSend;  //发送按钮

private slots:
   void do_send();        //发送
   void do_recvData();    //接收串口信息
};
#endif // WIDGET_H

在Widget构造函数中初始化串口,初始化窗口,设置信号与槽函数等,iniUI()中实现窗口布局和设计:

lubancat_qt_tutorial_code/QtSerial/widget.cpp(截取)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "widget.h"

void Widget::iniUI()
{
   //创建文本框,只读
   textEdit = new QTextEdit;
   textEdit->setReadOnly(1);

   lineEdit = new QLineEdit;
   BtnSend = new QPushButton("发送");

   QHBoxLayout *HLay =new QHBoxLayout;
   HLay->addWidget(lineEdit);
   HLay->addWidget(BtnSend);

   //创建垂直布局,并设置为主布局
   QVBoxLayout *VLay=new QVBoxLayout(this);
   VLay->addWidget(textEdit);         //添加textEdit
   VLay->addSpacing(5);               //添加空隙
   VLay->addLayout(HLay);             //添加HLay

   setLayout(VLay);    //设置为窗口的主布局
}

//......省略

Widget::Widget(QWidget *parent)
   : QWidget(parent)
{
   setGeometry(0,0,640,480);     //设置窗口大小
   iniUI();                      //窗口创建与初始化
   setWindowTitle("串口测试");    //设置窗口标题
   uart3.uart_open();            //连接串口

   QTimer* timerRead = new QTimer;
   timerRead->start(500);

   //信号与槽的关联
   connect(timerRead, SIGNAL(timeout()),this, SLOT(do_recvData()));
   connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(do_send()));
   connect(BtnSend,SIGNAL(clicked()),this,SLOT(do_send()));
}

先在窗口中创建一个文本框,并且设置只读,然后创建一个QLineEdit,作为输入端(支持回车发送等),然后创建一个“发送”按钮。

创建组件后,添加一个布局控件,来规划整体窗口,然后设置为窗口的主体布局。

3.2.4. 串口通讯程序

点击左边资源目录,添加新文件(创建一个uart类,父类是QObject):

gpio01.png

创建之后,在uart声明函数和变量等,在uart.cpp中实现:

lubancat_qt_tutorial_code/QtSerial/uart.cpp(截取部分)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "uart.h"

Uart::Uart(QObject *parent)
   : QObject{parent}
{
   _fd=0;
}

void Uart::uart_open(QString dev, speed_t buad)
{
   struct termios options;

   if ((_fd = open(dev.toUtf8().data(), O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
   {
      qDebug("open failed!");
      return;
   }

   // 读写
   fcntl (_fd, F_SETFL, O_RDWR) ;

   // 设置波特率,串口的其他参数设置参考下https://doc.embedfire.com/linux/rk356x/linux_base/zh/latest/linux_app/uart/uart.html#id12
   tcgetattr (_fd, &options);
   cfmakeraw   (&options) ;
   cfsetispeed (&options, buad) ;
   cfsetospeed (&options, buad) ;
   tcsetattr (_fd, TCSANOW, &options) ;
}

3.3. 运行测试例程

3.3.1. 硬件连接

板卡与PC电脑通过usb转串口连接:

鲁班猫板卡

USB转TTL

UART3_RX_M0

连接

TXD

UART3_TX_M0

连接

RXD

GND

连接

GND

3.3.2. 编译测试

选择 LubanCat_RK 编译套件,然后点击Qt Creator左下角的锤子符号,进行编译,会在构建目录下生成qt_serial可执行文件。 传输文件到板卡,然后执行命令:

# 复制可执行程序到板卡
scp qt_serial cat@192.168.103.110:/home/cat/qt

# 在debian10 带桌面的系统中运行,使用xcb
# 注意程序打开设备文件,需要root权限
sudo  ./qt_serial -platform xcb

板卡运行程序, PC端使用野火多功能串口,打开串口,设置默认串口参数 115200-N-8-1 ,然后点击发送:

gpio01.png

板端输入信息,然后点击发送或者回车发送:

gpio01.png

提示

远程部署和测试,ssh连接需要root用户。