导航

    全志在线开发者论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 在线文档
    • 社区主页

    Qt应用开发--国产工业开发板T113-i的部署教程

    创龙科技专区
    1
    1
    1400
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • R
      RiceChen LV 4 最后由 编辑

      Qt在工业上的使用场景包括工业自动化、嵌入式系统、汽车行业、航空航天、医疗设备、制造业和物联网应用。Qt被用来开发工业设备的用户界面、控制系统、嵌入式应用和其他工业应用,因其跨平台性和丰富的功能而备受青睐。

      Qt能够为工业领域带来什么好处:
      - Qt提供了强大的图形引擎,使开发人员能够创建具有吸引力和高性能的用户界面
      - Qt允许开发人员根据具体需求定制用户界面和功能。这对于满足不同行业和项目的独特需求至关重要,使工业应用能够实现个性化的解决方案
      - Qt提供了丰富的库和工具,涵盖了各种应用程序开发需求,包括图形、网络通信、多媒体处理、数据存储等。这简化了工业应用程序的开发流程
      - Qt可以轻松与各种硬件设备和通信协议集成,这对于工业自动化和控制系统来说非常重要,因为它们需要与各种传感器、执行器和其他工业设备进行通信

      创龙科技基于全志双核Cortex-A7@1.2GHz处理器T113-i,精心设计的全国产工业开发板,它提供了Qt的运行环境,可以让我们快速的部署工业领域的用户交互界面,控制系统等。

      接下来我们来聊聊如何在创龙科技T113-i工业开发板上部署Qt应用。

      开发板Qt运行环境

      开发板SDK准备

      • 创龙科技的资料中提供了开发板的SDK-T113-i_v1.0.tar.gz,需要解压ubuntu中解压出来:
      rice@rice:~$ mkdir t113             //创建t113工作目录,然后将压缩包拷贝到此目录
      rice@rice:~$ cd t113
      ....
      
      rice@rice:~/t113$ tar -zxvf SDK-T113-i_v1.0.tar.gz
      rice@rice:~/t113$ cd T113-i_v1.0/
      rice@rice:~/t113/T113-i_v1.0$ ls
      brandy  buildroot  device  install_tools.sh  out       rtos-dsp  tools
      build   build.sh   kernel  platform          test
      
      • 安装依赖软件,创龙科技提供了安装脚本:install_tools.sh,我们执行该脚本即可完成依赖工具的安装:
      rice@rice:~/t113/T113-i_v1.0$ ./install_tools.sh
      [sudo] password for rice: 
      Reading package lists... Done
      Building dependency tree       
      Reading state information... Done
      texinfo is already the newest version (6.5.0.dfsg.1-2).
      0 upgraded, 0 newly installed, 0 to remove and 121 not upgraded.
      Reading package lists... Done
      Building dependency tree       
      Reading state information... Done
      pkg-config is already the newest version (0.29.1-0ubuntu2).
      0 upgraded, 0 newly installed, 0 to remove and 121 not upgraded.
      Reading package lists... Done
      
      ......
      
      
      • 解压Buildroot dl--dl.tar.gz,其为 Buildroot dl 目录压缩包,用于存放从官网下载的开源软件包:
      rice@rice:~/t113$ tar -xvf dl.tar.gz -C ~/t113/buildroot/buildroot-201902/
      

      构建Qt固件

      • 在编译固件前,先清理一下SDK的编译和配置生成文件:
      rice@rice:~/t113/T113-i_v1.0$ ./build.sh distclean
      
      • 配置linux内核,处理器型号,显示方式,编译器等信息
      rice@rice:~/t113/T113-i_v1.0$ ./build.sh config
      Welcome to mkscript setup progress
      All available platform:
       0. linux
      Choice [linux]: 0
      All available linux_dev:
       0. bsp
       1. dragonboard
       2. longan
       3. tinyos
      Choice [longan]: 2
      All available kern_ver:
       0. linux-5.4
      Choice [linux-5.4]: 0
      All available ic:
       0. t113
       1. t113_i
      Choice [t113_i]: 1
      All available board:
       0. evb1
       1. evb1_auto
       2. evb1_auto_nand
       3. evb1_auto_nor
       4. tlt113-evm-emmc
       5. tlt113-evm-nand
       6. tlt113-minievm-emmc
       7. tlt113-minievm-nand
      Choice [tlt113-evm-nand]: 5
      All available output_configs:
       0. hdmi
       1. lvds-lcd
       2. mipi-lcd
       3. tft-lcd
       4. cvbs
      Choice [hdmi]: 0
      All available flash:
       0. default
       1. nor
      Choice [default]: 0
      All available build_root:
       0. buildroot-201902
       1. ubuntu
      Choice [buildroot-201902]: 0
      All available gnueabi:
       0. gnueabi
       1. gnueabihf
      Choice [gnueabi]: 0
      
      
      • 设置编译的环境变量:
      rice@rice:~/t113/T113-i_v1.0$ source ./build/envsetup.sh
      
      • 我们采用一键编译 SPL、U-Boot、Linux 内核和 buildroot文件系统。
      rice@rice:~/t113/T113-i_v1.0$ ./build.sh
      ACTION List: mklichee;========
      Execute command: mklichee 
      INFO: ----------------------------------------
      INFO: build lichee ...
      INFO: chip: sun8iw20p1
      INFO: platform: linux
      INFO: kernel: linux-5.4
      INFO: board: tlt113-evm-nand
      INFO: output: /home/rice/t113/T113-i_v1.0/out/t113_i/tlt113-evm-nand/longan
      INFO: ----------------------------------------
      INFO: build buildroot ...
      Prepare br toolchain gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabi.tar.xz...
      make: Entering directory '/home/rice/t113/T113-i_v1.0/buildroot/buildroot-201902'
      
      ...
      
      
      • 编译Qt库,使其开发板固件支持Qt应用运行环境:
      rice@rice:~/t113/T113-i_v1.0$ ./build.sh qt
      ACTION List: mkqt;========
      Execute command: mkqt 
      INFO: build Qt ...
      INFO: build arm-linux-gnueabi version's Qt
      /home/rice/t113/T113-i_v1.0/platform/framework/qt/qt-everywhere-src-5.12.5
      Using built-in specs.
      COLLECT_GCC=gcc
      COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
      OFFLOAD_TARGET_NAMES=nvptx-none
      OFFLOAD_TARGET_DEFAULT=1
      Target: x86_64-linux-gnu
      Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
      Thread model: posix
      
      .....
      
      
      • 打包系统镜像文件,执行之后,可以看到生成的固件文件,它默认生成两个版本的固件,分别是:nand固件和SD卡固件,我们是采用SD卡启动,所以使用SD卡固件。
      rice@rice:~/t113/T113-i_v1.0$ ./build.sh pack
      ACTION List: mkpack ;========
      Execute command: mkpack  
      INFO: packing firmware ...
      INFO: Use BIN_PATH: /home/rice/t113/T113-i_v1.0/device/config/chips/t113_i/bin
      copying tools file
      copying configs file
      copying product configs file
      /home/rice/t113/T113-i_v1.0/out/pack_out/aultls32.fex
      /home/rice/t113/T113-i_v1.0/out/pack_out/aultools.fex
      /home/rice/t113/T113-i_v1.0/out/pack_out/boot_package.cfg
      /home/rice/t113/T113-i_v1.0/out/pack_out/boot_package.fex
      
      ...... 
      
      dsp0.fex Len: 0x3fc78
      Vdsp0.fex Len: 0x4
      BuildImg 0
      Dragon execute image.cfg SUCCESS !
      ----------image is at----------
      
      size:613M  /home/rice/t113/T113-i_v1.0/out/t113_i_linux_tlt113-evm-nand-sdboot_uart0.img
      
      pack finish
      

      运行环境验证

      下载运行实例

      • 将编译打包后的固件(t113_i_linux_tlt113-evm-nand-sdboot_uart0.img)放到windows上,通过工具PhoenixCard.exe烧录到SD卡上。将SD卡插到读卡器上,然后插进电脑:

      • 创龙科技提供了qt的demo,我们将led_control的实例拷贝到板子上:
      rice@rice:~/t113/qt-demos/led_control/bin$ scp led_control root@ip:~/
      

      创龙T113-i上运行实例

      • 关闭默认的Qt运行程序,设置qt的环境变量
      root@T113-Tronlong:~# killall Launcher
      root@T113-Tronlong:~# source /etc/qtenv.sh 
      add /dev/input/event1 to Qt Application.
      find qt5 installed done
      
      • 运行实例验证Qt功能,运行效果如图:
      root@T113-Tronlong:~# ./led_control
      
      

      Qt开发环境

      开发环境下载

      • Qt开发环境下载,作者是使用Qt 5.12.0,下载链接:https://download.qt.io/archive/qt/5.12/5.12.0/,Ubuntu需要下载:qt-opensource-linux-x64-5.12.0.run

      开发环境交叉编译环境配置

      • 配置Debuggers
        • 点击菜单栏"Tools -> Options"
        • 击"Kits -> Debuggers -> Add -> Browse…"
        • 选择目标平台的GDB,路径:/home/rice/t113/T113-i_v1.0/out/t113_i/tlt113-evm-nand/longan/buildroot/host/usr/bin/arm-linux-gnueabi-gdb

      • 配置交叉工具链
        • 点击菜单栏"Tools -> Options"
        • 击"Kits -> Compilers -> Add -> GCC -> C++ -> Browse…"
        • 选择目标平台的交叉工具链,路径:/home/rice/t113/T113-i_v1.0/out/t113_i/tlt113-evm-nand/longan/buildroot/host/usr/bin/arm-linux-gnueabi-g++

      • 配置Qt Versions
        • 点击菜单栏"Tools -> Options"
        • 击"Kits -> Qt Versions -> Add -> GCC -> C++ -> Browse…"
        • 选择目标平台的Qt Versions,路径:/home/rice/t113/T113-i_v1.0/platform/framework/qt/qt-everywhere-src-5.12.5/Qt_5.12.5/bin/qmake

      • 配置Kits
        • 点击菜单栏"Tools -> Options"
        • 击"Kits -> Kits"
        • 将 Name 修改为"T113",Device type 选择"Generic Linux Device",Compiler 的 C++选择"T113-GCC",Debugger 选择"T113-Debugger",Qt version 选择"T113-qt5",点击 Apply,然后点击 OK 完成配置

      开发Qt应用

      • 作者开发了一个快速验证硬件功能的,主要功能包含:
      1. 板载LED灯控制,代码实现:
      static QString ledPath = "/sys/class/leds/user-led0";
      
      void rice::ledInit()
      {
          setLedStatus(0);
      
          ui->ledPushButton->setText("LED OFF");
          ui->ledPushButton->setStyleSheet("border-width:1px;"
                                           "border-style:solid; "
                                           "border-color:white;"
                                           "background-color:rgba(88, 88, 88, 200)");
      }
      
      void rice::ledDeinit()
      {
      
      }
      
      bool rice::setLedStatus(int status)
      {
          QString cmd = "echo " + QString::number(status) + " > " + ledPath + "/brightness";
          if (system(cmd.toStdString().c_str()) == -1) {
              printf("set led status failed!\n");
              return false;
          }
          return true;
      }
      
      int rice::getLedStatus(void)
      {
          QString cmd = "cat " + ledPath + "/brightness";
          FILE *fp = popen(cmd.toStdString().c_str(), "r");
          if (fp == nullptr) {
              return -1;
          }
      
          char led_status[32];
          if (fgets(led_status, sizeof(led_status), fp) == nullptr) {
              printf("fgets error: %s\n", cmd.toStdString().c_str());
              pclose(fp);
              return -1;
          }
      
          pclose(fp);
          return atoi(led_status);
      }
      
      void rice::on_ledPushButton_clicked()
      {
          int ledStatus = getLedStatus();
          if (ledStatus == 0) {
              setLedStatus(1);
              ui->ledPushButton->setText("LED ON");
              ui->ledPushButton->setStyleSheet("border-width:1px;"
                                               "border-style:solid; "
                                               "border-color:white;"
                                               "background-color:rgba(00, 205, 00, 255)");
          }
          else {
              setLedStatus(0);
              ui->ledPushButton->setText("LED OFF");
              ui->ledPushButton->setStyleSheet("border-width:1px;"
                                               "border-style:solid; "
                                               "border-color:white;"
                                               "background-color:rgba(88, 88, 88, 200)");
          }
      }
      
      1. 板载按键检测,代码实现:
      void rice::keyInit()
      {
          keyFd = open(keyPath.toUtf8().data(), O_RDONLY);
          if(keyFd == -1)
          {
              printf("Can not open file(%s)", keyPath.toUtf8().data());
              return;
          }
          ui->keyTextEdit->append("Key Monitor!\n");
          ui->keyTextEdit->append("Key user0 pressed!");
      
          keyNotify = new QSocketNotifier(this->keyFd, QSocketNotifier::Read, this);
          connect(this->keyNotify, SIGNAL(activated(int)), this, SLOT(keyHandler()));
      }
      
      void rice::keyDeinit()
      {
      
      }
      
      void rice::keyHandler()
      {
          struct input_event buf;
      
          if(read(keyFd, &buf, sizeof(struct input_event)) > 0)
          {
              if(buf.code == KEY_PROG1 && buf.value == 1)
              {
                  ui->keyTextEdit->append("Key user0 pressed!");
              }
          }
      }
      
      1. RTC时钟获取并显示,代码实现:
      void rice::dateInit()
      {
          struct rtc_time rtc_tm_temp;
          dateFd = open(datePath.toUtf8().data(), O_RDONLY);
          if(dateFd == -1)
          {
              printf("Can not open file(%s)", keyPath.toUtf8().data());
              return;
          }
          if(ioctl(dateFd, RTC_RD_TIME, &rtc_tm_temp) < 0)
          {
              printf("Get date failed");
              return;
          }
          ui->yearLineEdit->setText(QString::number(rtc_tm_temp.tm_year + 1900));
          ui->monthLineEdit->setText(QString::number(rtc_tm_temp.tm_mon + 1));
          ui->dayLineEdit->setText(QString::number(rtc_tm_temp.tm_mday));
      }
      
      void rice::dateDeint()
      {
      
      }
      
      1. 网络调试助手,代码实现:
      void rice::netInit()
      {
          server = new QTcpServer();
          socket = new QTcpSocket();
      }
      
      void rice::netDeint()
      {
      
      }
      
      void rice::netNewClientConnect()
      {
          socket = server->nextPendingConnection();
          connect(socket, &QTcpSocket::readyRead, this, &rice::netNewRcve);
      }
      
      void rice::on_netPushButton_clicked()
      {
          int port = ui->portLineEdit->text().toInt();
          if(ui->netPushButton->text() == tr("Open"))
          {
              if(ui->typeComboBox->currentText() == tr("Server"))
              {
                  connect(server, &QTcpServer::newConnection, this, &rice::netNewClientConnect);
                  if(!server->listen(QHostAddress::Any, port))
                  {
                      printf("Listen failed\n");
                      return;
                  }
              }
              else if(ui->typeComboBox->currentText() == tr("Client"))
              {
                  QString ip = ui->ipComboBox->currentText();
                  socket->abort();
                  socket->connectToHost(ip, port);
      
                  if(!socket->waitForConnected(3000))
                  {
                      printf("Connect server failed");
                      return;
                  }
                  connect(socket, &QTcpSocket::readyRead, this, &rice::netNewRcve);
              }
              ui->netPushButton->setText("Close");
          }
          else if(ui->netPushButton->text() == tr("Close"))
          {
              if(ui->typeComboBox->currentText() == tr("Server"))
              {
                  socket->abort();
                  server->close();
              }
              else if(ui->typeComboBox->currentText() == tr("Client"))
              {
                  socket->disconnectFromHost();
              }
              ui->netPushButton->setText("Open");
          }
      }
      
      void rice::on_sendPushButton_clicked()
      {
          if(socket->isOpen())
          {
              socket->write(ui->sendLineEdit->text().toUtf8().data());
          }
      }
      
      void rice::netNewRcve()
      {
          ui->recvTextEdit->append(socket->readAll());
      }
      
      void rice::on_typeComboBox_currentIndexChanged(const QString &arg1)
      {
          if(arg1 == tr("Server"))
          {
              ui->ipComboBox->setEditable(false);
          }
          else
          {
              ui->ipComboBox->setEditable(true);
          }
      }
      
      

      Qt应用验证

      1. 板载LED灯控制验证,当点击开关LED按钮时,LED灯会根据状态亮灭:

      1. 当应用运行起来时,会获取RTC时间,并显示:

      1. 当板载按键按下时,窗口会显示按键按下:

      1. 网络调试助手支持TCP客户端和TCP服务器两种类型,下面演示服务器验证。开发板上设置板子的IP,和端口号,然后通过PC上网络调试助手连接上板子,并克实现数据的收发:
      • 客户端往服务器发送数据

      • 服务器往客户端发送数据

      1 条回复 最后回复 回复 引用 分享 1
      • 1 / 1
      • First post
        Last post

      Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号

      行为准则 | 用户协议 | 隐私权政策