【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相关的资讯.
评论
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 122浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 74浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 111浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 126浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 209浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 66浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 79浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 172浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 227浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 127浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 96浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 145浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 95浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 161浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦