【RT-Thread开源秀】教你动手写TCP上位机与小熊派通信

背景

  • 关于上位机的文章,作者在之前就分享过好几个上位机的开发流程分享。如下表:
序号内容语言
1《如何定制自己的HID调试助手》C#
2《C# 串口上位机开发》C#
3《Qt 串口上位机开发》QT
4《教你动手写UDP协议栈 - OTA上位机》python
5《基于RT-THREAD nano的平衡车--上位机软件》QT
6《R-Plan上位机》QT
  • 上位机开发不限于语言,找我之前开发中,初衷就是那种方便就使用那种语言开发,如:C#, QT, python, VB等。

  • 本篇文章分享是采用QT开发的TCP上位机,功能:通过TCP上位机控制小熊派板载外设。

  • 上位机采用QT开发,小熊派跑RT-Thread,如下图为总体框图。

源代码仓库

  • 代码链接:https://gitee.com/RiceChen0/bearpi_rt-thread.git

  • 分支:tcp_demo

  • 如果你们觉得不错,记得加个:Star。


TCP上位机

  • 本上危机支持作为服务器也支持作为客户端,可以通过按键进行切换到不同的模式。该上位机主要功能:①控制板子LED,②调节扩展板E53_IA1上LED的亮度。
  • 不过属于是作为客户端还是服务器都可以实现上述两个功能。
  • 上位机功能实现主要有两个文件:bearpi.cpp和bearpi.h

TCP上位机开发说明:

  1. 在项目文件中添加如下内容:
QT       += network
  1. TCP网络编程需要用到的头文件:
#include <QTcpSocket>
#include <QTcpServer>
  1. bearpi.h头文件内容说明:申明了界面的事件槽函数,并且定义了Tcp_Server和TcpSocket的句柄。
#ifndef BEARPI_H
#define BEARPI_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QTcpServer>

QT_BEGIN_NAMESPACE
namespace Ui { class bearpi; }
QT_END_NAMESPACE

class bearpi : public QMainWindow
{
    Q_OBJECT

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


private slots:
    void on_mode_pushButton_clicked();

    void on_start_pushButton_clicked();

    void on_open_pushButton_clicked();

    void on_pwm_horizontalSlider_valueChanged(int value);

private:
    void switch_mode();
    void new_client_connect();

private:
    Ui::bearpi *ui;
    QTcpServer *server;
    QTcpSocket *socket;
};
#endif // BEARPI_H
  1. bearpi.cpp源文件构造函数内容说明:①实例化Tcp_Server和TcpSocket的句柄,②定义IP地址的lineEdit控件格式,③根据模式使能对应的控件。
bearpi::bearpi(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::bearpi)
{
    ui->setupUi(this);

    server = new QTcpServer();
    socket = new QTcpSocket();

    QRegExp ip_RegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$");
    QRegExpValidator *ip_format = new QRegExpValidator(ip_RegExp, this);
    ui->ip_lineEdit->setValidator(ip_format);

    switch_mode();
}
  1. bearpi.cpp源文件switch_mode()函数内容说明:①根据模式使能对应的控件。
void bearpi::switch_mode()
{
    if(ui->mode_pushButton->text() == tr("SERVER"))
    {
        ui->ip_lineEdit->setEnabled(false);
    }
    else if(ui->mode_pushButton->text() == tr("CLIENT"))
    {
        ui->ip_lineEdit->setEnabled(true);
    }
}
  1. bearpi.cpp源文件new_client_connect()函数内容说明:①当模式作为server时,有客户端请求建立连接时的信号槽函数,主要与客户端建立socket句柄。
void bearpi::new_client_connect()
{
    socket = server->nextPendingConnection();
    qDebug() << "A Client connect!";
}
  1. bearpi.on_start_pushButton_clicked()函数内容说明:①当作为服务器,则进行建立服务器,并联建立客户端连接槽函数。①当作为客户端,根据IP地址和端口号与服务器建立连接。
void bearpi::on_start_pushButton_clicked()
{
    if(ui->start_pushButton->text() == tr("START"))
    {
        if(ui->mode_pushButton->text() == tr("SERVER"))
        {
            int port = 0;

            connect(server,&QTcpServer::newConnection,this,&bearpi::new_client_connect);

            port = ui->port_lineEdit->text().toInt();

            if(!server->listen(QHostAddress::Any, port))
            {
                qDebug() << server->errorString();
                return;
            }
            qDebug() << "Listen successfully";
        }
        else if(ui->mode_pushButton->text() == tr("CLIENT"))
        {
            QString ip;
            int port = 8080;

            ip = ui->ip_lineEdit->text();
            port = ui->port_lineEdit->text().toInt();

            socket->abort();
            socket->connectToHost(ip, port);

            if(!socket->waitForConnected(3000))
            {
                qDebug() << "Connect failed";
                return;
            }
            qDebug() << "Connect successfully";
        }
        ui->start_pushButton->setText(tr("STOP"));
        ui->mode_pushButton->setEnabled(false);
    }
    else if(ui->start_pushButton->text() == tr("STOP"))
    {
        if(ui->mode_pushButton->text() == tr("SERVER"))
        {
            socket->abort();
            server->close();

        }
        else if(ui->mode_pushButton->text() == tr("CLIENT"))
        {
            socket->disconnectFromHost();
        }
        ui->start_pushButton->setText(tr("START"));
        ui->mode_pushButton->setEnabled(true);
    }
}
  1. bearpi.cpp源文件on_open_pushButton_clicked()函数内容说明:①控制小熊派板载LED的开关的槽函数,②通过发送led_open和led_close字符串来控制板载LED。
void bearpi::on_open_pushButton_clicked()
{
    qDebug() << ui->open_pushButton->text();
    if(ui->open_pushButton->text() == tr("OPEN LED"))
    {
        socket->write("led_open");
        socket->flush();
        ui->open_pushButton->setText(tr("CLOSE LED"));
    }
    else if(ui->open_pushButton->text() == tr("CLOSE LED"))
    {
        socket->write("led_close");
        socket->flush();
        ui->open_pushButton->setText(tr("OPEN LED"));
    }
}
  1. bearpi.cpp源文件on_pwm_horizontalSlider_valueChanged()函数内容说明:①调节扩展板E53_IA1上LED的亮度的槽函数,②根据滑动条的值调节扩展板E53_IA1上LED的PWM。
void bearpi::on_pwm_horizontalSlider_valueChanged(int value)
{
    char pwm_str[1] = {0};

    pwm_str[0] = (char)value;

    socket->write(pwm_str);
    socket->flush();

    qDebug() << pwm_str[0];
}

TCP上位机演示:

1. 作为server:
2. 作为client:

小熊派开发

  • 为了快速的开发,我直接采用rt-thread,它提供的丰富的组件,不用自己造轮子。小熊派上的功能主要是启动一个client,然后通过接收到上位机的命令之后通过PWM或GPIO控制LED。
  • 网络:采用小熊派板载模组ESP8266。使用RT-Thread的AT组件,SAL组件,netdev组件。
  • PWM:使用了PWM设备驱动框架
  • demo中小熊派作为客户端,TCP上位机作为服务器。上位机通过TCP控制小熊派。

小熊派代码说明:

  1. 通过RT-THREAD强大的组件,使我们编程更加统一简单。
  • 创建一个socket,然后连接到对应上位机服务器。
  • 根据设备名获取PWM的句柄,然后初始化pwm的初始值并使能。
  • 创建一个线程,用于处理服务器下发的指令及数据。
void bearpi_client(int argc, char **argv)
{
  int ret;
  struct hostent *host;
  struct sockaddr_in server_addr;

  host = gethostbyname(IP_ADDR);

  if ((sock_client_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    rt_kprintf("Socket error\n");
    return;
  }

  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(PORT);
  server_addr.sin_addr = *((struct in_addr *)host->h_addr);
  rt_memset(&(server_addr.sin_zero), 0sizeof(server_addr.sin_zero));

  if (connect(sock_client_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
  {
    rt_kprintf("Connect fail!\n");
    closesocket(sock_client_fd);
    return;
  }

  pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);

  rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);

  rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

  rt_thread_init(&bearpi_thread,
                "bearpi",
                bearpi_entry,
                RT_NULL,
                &bearpi_stack[0],
                sizeof(bearpi_stack),
                105);
  rt_thread_startup(&bearpi_thread);

  return;
}
MSH_CMD_EXPORT(bearpi_client, a tcp client sample);
  1. 接受数据线程:根据命令的类型进行调节板载的LED。
void bearpi_entry(void* paramenter)
{
  char recv_data[BUFSZ] = {0};
  uint32_t recv_len = 0;

  uint32_t is_open = 0;
  while (1)
  {
    recv_len = recv(sock_client_fd, recv_data, BUFSZ - 10);

    if(recv_len > 0)
    {
      if(strncmp(recv_data, "led_open"8) == 0)
      {
        rt_pin_write(LED0_PIN, PIN_HIGH);
        is_open = RT_TRUE;
      }
      else if(strncmp(recv_data, "led_close"1) == 0)
      {
        rt_pin_write(LED0_PIN, PIN_LOW);
        is_open = RT_FALSE;
        rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, 0);
      }
      else
      {
        if(is_open == RT_TRUE)
        {
          pulse = period / 100 * recv_data[0];
          rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
        }
      }
    }
  }
}

吐槽说明:

  • 在RT-THREAD的驱动中,有一个做的不是很友好的地方如下图:
  • drv_pwm.c中了为了划分不同的型号进行的归类,RT-THREAD值进行大类归类,而没有进行细化不同的型号。如L4系列,但实际STM32L431并没有那么多TIM,所以当我们使能PWM这个功能时,会编译不过。。
  • 所以这里需要细分不同型号,但在作者工程中,把报错的地方直接注释了。

整体功能演示



RTThread物联网操作系统 帮助您了解RT-Thread相关的资讯.
评论
  • 《高速PCB设计经验规则应用实践》+PCB绘制学习与验证读书首先看目录,我感兴趣的是这一节;作者在书中列举了一条经典规则,然后进行详细分析,通过公式推导图表列举说明了传统的这一规则是受到电容加工特点影响的,在使用了MLCC陶瓷电容后这一条规则已经不再实用了。图书还列举了高速PCB设计需要的专业工具和仿真软件,当然由于篇幅所限,只是介绍了一点点设计步骤;我最感兴趣的部分还是元件布局的经验规则,在这里列举如下:在这里,演示一下,我根据书本知识进行电机驱动的布局:这也算知行合一吧。对于布局书中有一句:
    wuyu2009 2024-11-30 20:30 88浏览
  • 国产光耦合器正以其创新性和多样性引领行业发展。凭借强大的研发能力,国内制造商推出了适应汽车、电信等领域独特需求的专业化光耦合器,为各行业的技术进步提供了重要支持。本文将重点探讨国产光耦合器的技术创新与产品多样性,以及它们在推动产业升级中的重要作用。国产光耦合器创新的作用满足现代需求的创新模式新设计正在满足不断变化的市场需求。例如,高速光耦合器满足了电信和数据处理系统中快速信号传输的需求。同时,栅极驱动光耦合器支持电动汽车(EV)和工业电机驱动器等大功率应用中的精确高效控制。先进材料和设计将碳化硅
    克里雅半导体科技 2024-11-29 16:18 161浏览
  • 国产光耦合器因其在电子系统中的重要作用而受到认可,可提供可靠的电气隔离并保护敏感电路免受高压干扰。然而,随着行业向5G和高频数据传输等高速应用迈进,对其性能和寿命的担忧已成为焦点。本文深入探讨了国产光耦合器在高频环境中面临的挑战,并探索了克服这些限制的创新方法。高频性能:一个持续关注的问题信号传输中的挑战国产光耦合器传统上利用LED和光电晶体管进行信号隔离。虽然这些组件对于标准应用有效,但在高频下面临挑战。随着工作频率的增加,信号延迟和数据保真度降低很常见,限制了它们在电信和高速计算等领域的有效
    腾恩科技-彭工 2024-11-29 16:11 106浏览
  • RDDI-DAP错误通常与调试接口相关,特别是在使用CMSIS-DAP协议进行嵌入式系统开发时。以下是一些可能的原因和解决方法: 1. 硬件连接问题:     检查调试器(如ST-Link)与目标板之间的连接是否牢固。     确保所有必要的引脚都已正确连接,没有松动或短路。 2. 电源问题:     确保目标板和调试器都有足够的电源供应。     检查电源电压是否符合目标板的规格要求。 3. 固件问题: &n
    丙丁先生 2024-12-01 17:37 57浏览
  • 在电子技术快速发展的今天,KLV15002光耦固态继电器以高性能和强可靠性完美解决行业需求。该光继电器旨在提供无与伦比的电气隔离和无缝切换,是现代系统的终极选择。无论是在电信、工业自动化还是测试环境中,KLV15002光耦合器固态继电器都完美融合了效率和耐用性,可满足当今苛刻的应用需求。为什么选择KLV15002光耦合器固态继电器?不妥协的电压隔离从本质上讲,KLV15002优先考虑安全性。输入到输出隔离达到3750Vrms(后缀为V的型号为5000Vrms),确保即使在高压情况下,敏感的低功耗
    克里雅半导体科技 2024-11-29 16:15 119浏览
  • 最近几年,新能源汽车愈发受到消费者的青睐,其销量也是一路走高。据中汽协公布的数据显示,2024年10月,新能源汽车产销分别完成146.3万辆和143万辆,同比分别增长48%和49.6%。而结合各家新能源车企所公布的销量数据来看,比亚迪再度夺得了销冠宝座,其10月新能源汽车销量达到了502657辆,同比增长66.53%。众所周知,比亚迪是新能源汽车领域的重要参与者,其一举一动向来为外界所关注。日前,比亚迪汽车旗下品牌方程豹汽车推出了新车方程豹豹8,该款车型一上市就迅速吸引了消费者的目光,成为SUV
    刘旷 2024-12-02 09:32 62浏览
  • 戴上XR眼镜去“追龙”是种什么体验?2024年11月30日,由上海自然博物馆(上海科技馆分馆)与三湘印象联合出品、三湘印象旗下观印象艺术发展有限公司(下简称“观印象”)承制的《又见恐龙》XR嘉年华在上海自然博物馆重磅开幕。该体验项目将于12月1日正式对公众开放,持续至2025年3月30日。双向奔赴,恐龙IP撞上元宇宙不久前,上海市经济和信息化委员会等部门联合印发了《上海市超高清视听产业发展行动方案》,特别提到“支持博物馆、主题乐园等场所推动超高清视听技术应用,丰富线下文旅消费体验”。作为上海自然
    电子与消费 2024-11-30 22:03 75浏览
  • 学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&
    youyeye 2024-11-30 14:30 65浏览
  • 在现代科技浪潮中,精准定位技术已成为推动众多关键领域前进的核心力量。虹科PCAN-GPS FD 作为一款多功能可编程传感器模块,专为精确捕捉位置和方向而设计。该模块集成了先进的卫星接收器、磁场传感器、加速计和陀螺仪,能够通过 CAN/CAN FD 总线实时传输采样数据,并具备内部存储卡记录功能。本篇文章带你深入虹科PCAN-GPS FD的技术亮点、多场景应用实例,并展示其如何与PCAN-Explorer6软件结合,实现数据解析与可视化。虹科PCAN-GPS FD虹科PCAN-GPS FD的数据处
    虹科汽车智能互联 2024-11-29 14:35 149浏览
  • By Toradex胡珊逢简介嵌入式领域的部分应用对安全、可靠、实时性有切实的需求,在诸多实现该需求的方案中,QNX 是经行业验证的选择。在 QNX SDP 8.0 上 BlackBerry 推出了 QNX Everywhere 项目,个人用户可以出于非商业目的免费使用 QNX 操作系统。得益于 Toradex 和 QNX 的良好合作伙伴关系,用户能够在 Apalis iMX8QM 和 Verdin iMX8MP 模块上轻松测试和评估 QNX 8 系统。下面将基于 Apalis iMX8QM 介
    hai.qin_651820742 2024-11-29 15:29 151浏览
  • 学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&
    youyeye 2024-11-29 14:30 118浏览
  • 光耦合器作为关键技术组件,在确保安全性、可靠性和效率方面发挥着不可或缺的作用。无论是混合动力和电动汽车(HEV),还是军事和航空航天系统,它们都以卓越的性能支持高要求的应用环境,成为现代复杂系统中的隐形功臣。在迈向更环保技术和先进系统的过程中,光耦合器的重要性愈加凸显。1.混合动力和电动汽车中的光耦合器电池管理:保护动力源在电动汽车中,电池管理系统(BMS)是最佳充电、放电和性能监控背后的大脑。光耦合器在这里充当守门人,将高压电池组与敏感的低压电路隔离开来。这不仅可以防止潜在的损坏,还可以提高乘
    腾恩科技-彭工 2024-11-29 16:12 119浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2024-12-02 10:40 63浏览
  • 艾迈斯欧司朗全新“样片申请”小程序,逾160种LED、传感器、多芯片组合等产品样片一触即达。轻松3步完成申请,境内免费包邮到家!本期热荐性能显著提升的OSLON® Optimal,GF CSSRML.24ams OSRAM 基于最新芯片技术推出全新LED产品OSLON® Optimal系列,实现了显著的性能升级。该系列提供五种不同颜色的光源选项,包括Hyper Red(660 nm,PDN)、Red(640 nm)、Deep Blue(450 nm,PDN)、Far Red(730 nm)及Ho
    艾迈斯欧司朗 2024-11-29 16:55 157浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦