【Qt5】多线程串口

news2024/11/24 2:35:48

文章目录

  • 原版代码工程
  • 增加QCustomplot实时画图的源码工程
  • 源码

原版代码工程

源码下载链接:
链接:https://pan.baidu.com/s/15pWzadPwOx_OfJGtvL-MjA
提取码:lief
–来自百度网盘超级会员V5的分享

在这里插入图片描述

增加QCustomplot实时画图的源码工程

在这里插入图片描述源码:
链接:https://pan.baidu.com/s/1DJKV7RY3C_1nQ1K2iNP61w
提取码:lief
–来自百度网盘超级会员V5的分享

下位机arduino测试代码:

#include <Arduino.h>

unsigned char data_to_send[100] = {0};

int acc_data[3] = {0};
int gyro_data[3] = {0};

/**********为了匿名四轴上位机的协议定义的变量****************************/
//cup为小端模式存储,也就是在存储的时候,低位被存在0字节,高位在1字节
#define BYTE0(dwTemp)       (*(char *)(&dwTemp))     //取出int型变量的低字节
#define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))     //    取存储在此变量下一内存字节的内容,高字节
#define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))

/* 
发送给上位机的数据帧定义 
@桢头--功能字--长度--数据(一个或多个,具体看协议说明)-校验
@前2个字节为帧头0xAAAA 
@第3个字节为帧ID,应设置为0xF1~0xFA中的一个 
@第4个字节为报文数据长度(dlc) 
@第5个字节开始到第5+dlc-1个字节为要传输的数据内容段,每个数据场为高字节在前,地字节在后 
@第5+dlc个字节为CheckSum,为第1个字节到第5+dlc-1个字节所有字节的值相加后,保留结果的低八位作为CheckSum 
*/  
void Data_Send_Senser(unsigned int pst)  //按照协议的要求处理数据,pst为包含多个数据的数组,但这里为一个数据
{
    unsigned char  _cnt=0;
    unsigned char  i=0;
    unsigned int j=0,temp;
    unsigned char sum = 0;
    
    //char 类型为两个字节
    data_to_send[_cnt++]=0xAA;  //桢头
    data_to_send[_cnt++]=0xAA;
    data_to_send[_cnt++]=0x02;  //功能字
    data_to_send[_cnt++]=0;     //需要发送数据的字节数,暂时给0,后面在赋值。
    data_to_send[_cnt++]=pst&0x00ff;  //数据的低8位
    data_to_send[_cnt++]=pst>>8;  //数据的高8位
    
    
    
    data_to_send[3] = _cnt-4;   //长度
    
    for(i=0; i<_cnt; i++)
    {
      sum = sum+ data_to_send[i];  //校验位
    }
    
    data_to_send[_cnt++] =sum; //计算校验位

    Serial.write(data_to_send,_cnt);  
}

/* 
发送给上位机的数据帧定义 
@桢头--功能字--长度--数据(一个或多个,具体看协议说明)-校验
@前2个字节为帧头0xAAAA 
@第3个字节为帧ID,应设置为0xF1~0xFA中的一个 
@第4个字节为报文数据长度(dlc) 
@第5个字节开始到第5+dlc-1个字节为要传输的数据内容段,每个数据场为高字节在前,地字节在后 
@第5+dlc个字节为CheckSum,为第1个字节到第5+dlc-1个字节所有字节的值相加后,保留结果的低八位作为CheckSum 
*/  
void data_to_computer(int* acc_data,int* gyro_data)
{
    unsigned char  data_to_send[23] = {0};
    unsigned char i = 0;
    unsigned char cnt = 0;
    unsigned char sum = 0;
    
    data_to_send[cnt++]=0xAA;     //帧头:AAAA
    data_to_send[cnt++]=0xAA;
    data_to_send[cnt++]=0x02;     //功能字:OXF2
    data_to_send[cnt++]=0;         //需要发送数据的字节数,暂时给0,后面在赋值。

    data_to_send[cnt++] = BYTE1(acc_data[0]);//取data[0]数据的高字节,
    data_to_send[cnt++] = BYTE0(acc_data[0]);
    data_to_send[cnt++] = BYTE1(acc_data[1]);
    data_to_send[cnt++] = BYTE0(acc_data[1]);
    data_to_send[cnt++] = BYTE1(acc_data[2]);
    data_to_send[cnt++] = BYTE0(acc_data[2]);

    data_to_send[cnt++] = BYTE1(gyro_data[0]);//取data[0]数据的高字节,
    data_to_send[cnt++] = BYTE0(gyro_data[0]);
    data_to_send[cnt++] = BYTE1(gyro_data[1]);
    data_to_send[cnt++] = BYTE0(gyro_data[1]);
    data_to_send[cnt++] = BYTE1(gyro_data[2]);
    data_to_send[cnt++] = BYTE0(gyro_data[2]);

    data_to_send[cnt++]=0;
    data_to_send[cnt++]=0;
    data_to_send[cnt++]=0;
    data_to_send[cnt++]=0;
    data_to_send[cnt++]=0;
    data_to_send[cnt++]=0;

    data_to_send[3] = cnt-4;//计算总数据的字节数。

    for(i=0;i<cnt;i++) //对于for语句,当不写大括号的时候,只执行到下面第一个分号结束。
    {
        sum+=data_to_send[i];
    }
    data_to_send[cnt++] = sum;    //计算校验位
    Serial.write(data_to_send,cnt);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  randomSeed(analogRead(0));

  pinMode(8,OUTPUT); 
}

void loop() {

  // unsigned char buff[6];
  // unsigned char i;

  // for(i = 0;i<6;i++)
  // {
  //   buff[i] = random(65535);
  // }

  //   acc_data[0] = (buff[0] << 8) | buff[1];//x轴高8位左移8位或上低8位
  //   acc_data[1] = (buff[2] << 8) | buff[3];
  //   acc_data[2] = (buff[4] << 8) | buff[5];

  //   for(i = 0;i<6;i++)
  //   {
  //       buff[i] = random(65535);
  //   }

  //   gyro_data[0] = (buff[0] << 8) | buff[1];//x轴高8位左移8位或上低8位
  //   gyro_data[1] = (buff[2] << 8) | buff[3];
  //   gyro_data[2] = (buff[4] << 8) | buff[5];


 // data_to_computer(acc_data, gyro_data);

  digitalWrite(8,HIGH);


//   unsigned int num = random(100);
//   Data_Send_Senser(num);
  for(int i = 0; i < 255; i++)
  {
    Data_Send_Senser(i);
    delay(2); // ms      
  }
           

  digitalWrite(8,LOW);
  
  //delayMicroseconds(1500); // us
}

源码

mainwindows.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qDebug() <<"main" <<QThread::currentThread();
    qRegisterMetaType<serialportplus::Settings>("serialportplus::Settings");
    initUI();
    initSerialPort();
}

MainWindow::~MainWindow()
{
    delete ui;
}

/*
 * 函数功能:完成对串口助手界面的初始化
 */
void MainWindow::initUI()
{
    //增加端口号选择项
    for (int i = 1; i <= 15; i++)
    {
        ui->cboPortName->addItem(QString("COM%1").arg(i));
    }

    //设置端口号波特率
    ui->cboBaudrate->addItem(QString("1200"),QSerialPort::Baud1200);
    ui->cboBaudrate->addItem(QString("2400"),QSerialPort::Baud2400);
    ui->cboBaudrate->addItem(QString("4800"),QSerialPort::Baud4800);
    ui->cboBaudrate->addItem(QString("9600"),QSerialPort::Baud9600);
    ui->cboBaudrate->addItem(QString("19200"),QSerialPort::Baud19200);
    ui->cboBaudrate->addItem(QString("38400"),QSerialPort::Baud38400);
    ui->cboBaudrate->addItem(QString("57600"),QSerialPort::Baud57600);
    ui->cboBaudrate->addItem(QString("115200"),QSerialPort::Baud115200);

    //设置端口数据位数
    ui->cboDataBit->addItem("8",QSerialPort::Data8);
    ui->cboDataBit->addItem("7",QSerialPort::Data7);
    ui->cboDataBit->addItem("6",QSerialPort::Data6);
    ui->cboDataBit->addItem("5",QSerialPort::Data5);

    //设置端口校验方式
    ui->cboParity->addItem("Odd",QSerialPort::OddParity);
    ui->cboParity->addItem("Even",QSerialPort::EvenParity);
    ui->cboParity->addItem("None",QSerialPort::NoParity);

    //设置端口停止位
    ui->cboStopBit->addItem("1",QSerialPort::OneStop);
    ui->cboStopBit->addItem("1.5",QSerialPort::OneAndHalfStop);
    ui->cboStopBit->addItem("2",QSerialPort::TwoStop);

    //设置端口流控制
    ui->cboFlowContral->addItem("None",QSerialPort::NoFlowControl);
    ui->cboFlowContral->addItem("RTS/CTS",QSerialPort::HardwareControl);
    ui->cboFlowContral->addItem("XON/XOFF",QSerialPort::SoftwareControl);

    //设置定时重发时间,单位ms
    ui->lineEdit->setText("1000");
    //定时时间到,则执行timeup函数
    connect(&m_timer, &QTimer::timeout, this,&MainWindow::timeUp);
}

/*
 * 函数功能:完成对串口的初始化,设置串口子线程
 */
void MainWindow::initSerialPort()
{
    //将串口对象的相关操作,放入子线程
    m_serial.moveToThread(&m_thread);
    //子线程启动
    m_thread.start();

    /*分别是界面对串口发出的启动、停止和发送数据的信号*/
    connect(this, &MainWindow::sigStart,&m_serial, &serialportplus::startPort);
    connect(this, &MainWindow::sigStop,&m_serial, &serialportplus::stopPort);
    connect(this, &MainWindow::sigSend,&m_serial, &serialportplus::sendData);

    /*分别是串口对界面发出的启动、停止和接收数据的信号*/
    connect(&m_serial, &serialportplus::sigStarted,this, &MainWindow::started);
    connect(&m_serial, &serialportplus::sigStop,this, &MainWindow::stoped);
    connect(&m_serial, &serialportplus::sigReceived,this, &MainWindow::receiveData);
}

/*
 * 函数功能:当界面关闭时,子线程也要进行关闭
 */
void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
    //打印界面主线程地址
    qDebug() <<"main" <<QThread::currentThread();
    //向发送串口发送串口停止的信号
    emit sigStop();

    //串口子线程关闭
    m_thread.quit();
    //等待串口子线程完全关闭
    m_thread.wait();

}


/*
 * 函数功能:根据串口打开按钮判断是否打开串口,
 *         当串口打开时,对串口参数进行设置,并向串口子线程发出串口打开信号,否则发出关闭信号
 */
void MainWindow::on_btnOpenPort_clicked()
{
    //获取串口打开按钮的文本
    QString text= ui->btnOpenPort->text();
    //当按钮关闭时,打开串口,并设置相关参数,向串口子线程发送串口打开信号
    if(text ==  QString::fromLocal8Bit("打开串口"))
    {
        serialportplus::Settings s;
        s.name= ui->cboPortName->currentText();
        s.baudRate= (QSerialPort::BaudRate)ui->cboBaudrate->currentData().toInt();
        s.dataBits = (QSerialPort::DataBits)ui->cboDataBit->currentData().toInt();
        s.stopBits= (QSerialPort::StopBits)ui->cboStopBit->currentData().toInt();
        s.parity= (QSerialPort::Parity)ui->cboParity->currentData().toInt();
        s.flowControl = (QSerialPort::FlowControl)ui->cboFlowContral->currentData().toInt();
        emit sigStart(s);
    }
     //当按钮打开时,关闭串口,向串口子线程发送串口关闭信号
    else
    {
        emit sigStop();
    }

}

/*
 * 函数功能:点击发送按钮时,执行串口发送
 */
void MainWindow::on_btnSend_clicked()
{
    //获取所要发送的文本
    QString strSend = ui->SendplainTextEdit->toPlainText();
    //将所要发送的文本存入arr变量
    QByteArray arr = strSend.toUtf8();
    //将arr变量通过信号发给串口子线程
    emit sigSend(arr);
}

/*
 * 函数功能:接收串口子线程发出启动的信号,对串口的按钮和参数设置的界面进行管理
 */
void MainWindow::started()
{
    //串口打开按钮文本切换,切换为“关闭串口”
    ui->btnOpenPort->setText(QString::fromLocal8Bit("关闭串口"));
    //串口参数处于不可更改的状态
    ui->groupBox->setEnabled(false);
}

/*
 * 函数功能:接收串口子线程发出停止的信号,对串口的按钮和参数设置的界面进行管理
 */
void MainWindow::stoped(int status)
{
    Q_UNUSED(status);
    //串口打开按钮文本切换,切换为“打开串口”
    ui->btnOpenPort->setText(QString::fromLocal8Bit("打开串口"));
    //串口参数处于可更改的状态
    ui->groupBox->setEnabled(true);
}

/*
 * 函数功能:接收串口子线程发出数据接收的信号,界面接收串口子线程发送的数据,并将其显示到界面上
 */
void MainWindow::receiveData(QByteArray data)
{
    //将接收的数据进行转换
    QString strText = QString(data);
    //获取当前接收数据的时间
    QDateTime current_date_time = QDateTime::currentDateTime();
    //显示当前接收数据的时间
    QString  t  = current_date_time.toString("yyyy-MM-dd hh:mm:ss.zzz : ");
    //显示当前接收的数据
    ui->RecveeiveplainTextEdit->appendPlainText( t + strText + "\n" );
}

/*
 * 函数功能:定时发送状态改变响应函数
 */
void MainWindow::on_checkBox_stateChanged(int arg1)
{
    //当定时发送被勾选时
    if(arg1)
    {
        //定时器启动
        m_timer.start(ui->lineEdit->text().toInt());
    }
    //当定时发送未被勾选时
    else
    {
        //定时器停止
        m_timer.stop();
    }
}

/*
 * 函数功能:定时时间到时,执行串口发送函数
 */
void MainWindow::timeUp()
{
    qDebug() << "timeup";

    //串口发送函数
    on_btnSend_clicked();
}

mainwindows.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include<QSerialPort>
#include<QDateTime>
#include<QTimer>
#include<QDebug>
#include<QThread>

#include"serialportplus.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    //界面初始化函数
    void initUI();
    //端口初始化函数
    void initSerialPort();
    //界面关闭事件
    void closeEvent(QCloseEvent *event);

private:
    Ui::MainWindow *ui;

    //创建一个自定义的串口类对象
    serialportplus m_serial;
    //创建一个线程对象
    QThread m_thread;
    //创建一个定时器对象
    QTimer m_timer;



signals:

    // 分别是界面对串口发出的启动、停止和发送数据的信号
    void sigStart(serialportplus::Settings s);
    void sigStop();
    void sigSend(QByteArray data);

public slots:

    // 分别是串口对界面发出的启动、停止和接收数据的信号时,所要执行的操作
    void started();
    void stoped(int status);
    void receiveData(QByteArray data);


private slots:
    void timeUp();
    void on_btnOpenPort_clicked();
    void on_btnSend_clicked();
    void on_checkBox_stateChanged(int arg1);
};
#endif // MAINWINDOW_H

serialportplus.cpp

#include "serialportplus.h"

/*
 * 函数功能:对串口接收到数据的信号进行响应,并向界面主线程发送接收到的数据
 */
serialportplus::serialportplus()
{
    //当串口子线程接收到数据时,向界面主线程发出数据接收的信号
    connect(this, &QSerialPort::readyRead, [this]()
    {
        qDebug() << QString::fromLocal8Bit ("接收") << QThread::currentThread();
        //读取串口接收的数据
        QByteArray arr = readAll();
        //将数据通过信号发给界面主线程
        emit sigReceived(arr);
    });
}

/*
 * 函数功能:接收界面主线程发出开始信号,接收串口参数并对设置,
 *         同时根据串口状态发出启动或停止信号。
 */
void serialportplus::startPort(serialportplus::Settings sets)
{
    /*设置串口参数*/
    setPortName(sets.name);
    setParity(sets.parity);
    setBaudRate(sets.baudRate);
    setDataBits(sets.dataBits);
    setStopBits(sets.stopBits);
    setFlowControl(sets.flowControl);

    qDebug() << QString::fromLocal8Bit ("启动") <<QThread::currentThread();

    //判断串口是否处于可读写状态
    if(open(QIODevice::ReadWrite))
    {
        //串口处于可读写状态,发出向界面主线程启动信号
        emit sigStarted();
    }
    else
    {
        //串口不处于可读写状态,发出向界面主线程停止信号
        emit sigStop(1);
    }
}

/*
 * 函数功能:接收界面主线程发送的停止信号,串口关闭
 */
void serialportplus::stopPort()
{
    qDebug() << QString::fromLocal8Bit ("停止") <<QThread::currentThread();
    //判断串口是否关闭
    if(isOpen())
    {
        //关闭串口
        close();
    }
    //向界面主线程发出停止信号
    emit sigStop(0);
}

/*
 * 函数功能:接收界面主线程发出的数据发送信号,串口进行数据发送
 */
void serialportplus::sendData(QByteArray arr)
{
    qDebug() << QString::fromLocal8Bit ("发送") <<QThread::currentThread();
    //判断串口是否关闭


    if(isOpen())
    {
        //发送数据
        write(arr);
    }
}

serialportplus.h

#ifndef SERIALPORTPLUS_H
#define SERIALPORTPLUS_H

#include <QSerialPort>
#include<QThread>
#include<QDebug>

class serialportplus : public QSerialPort
{
    Q_OBJECT
public:

    //串口接收数据的函数
    serialportplus();

    //串口设置
    struct Settings
    {
       QString name;//端口名称COM1、COM2
       BaudRate baudRate;//波特率
       DataBits dataBits;//数据位
       Parity parity;//奇偶校验
       StopBits stopBits;//停止位
       FlowControl flowControl;//流控制
     };

public slots:
    // 分别是界面对串口发出的启动、停止和发送数据的信号时,所要执行的操作
    void startPort(Settings sets);
    void stopPort();
    void sendData(QByteArray arr);

signals:
    // 分别是串口对界面发出的启动、停止和接收数据的信号
    void sigStarted();
    void sigStop(int status);
    void sigReceived(QByteArray data);
};

#endif // SERIALPORTPLUS_H

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/489847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Mybatis】增删改查

1.添加相应的jar包 2.创建持久化类 在src目录下创建一个名为com.mybatis.po的包 创建持久化类MyUser,包含三个属性&#xff08;uid,uname,usex) package com.mybatis.po; /***springtest数据库中user表的持久化类*/ public class MyUser {private Integer uid;//主键private…

滴水逆向三期笔记与作业——02C语言——02数据类型

海哥牛逼 这里写自定义目录标题 一、C语言如何变成汇编1、裸函数 二、调用约定1、常见的几种调用约定 三、程序的真正入口四、数据类型4.1 C语言中的数据类型 作业 一、C语言如何变成汇编 1、裸函数 裸函数使用特殊方式定义&#xff0c;编译器和连接器并不会为其生成提升堆栈…

华为网工实验(VRRP多网关负载分担,OSPF基础操作)

采用VRRP多网关负载分担实现流量的负载均衡 配置思路&#xff1a;首先配置各个接口ip,让设备间能够实现通信&#xff0c;采用OSPF协议实现通信&#xff0c;然后AR2 AR3创建两个备份组&#xff0c;主备不同的两个备份组 组网图 #先设备命名并配置IP&#xff0c;三台设备类似&a…

路由器拨号密码恢复

背景 路由器拨号上网的密码因时间久远遗忘了&#xff0c;恢复并记录下过程。 步骤 1&#xff0c;安装wireshark choco install wireshark -y 注意 实践发现wireshark安装后&#xff0c;启动提示还需要安装Npcap 或者 Winpcap, 不过&#xff0c;在winpcap官网提示它已不再开…

虚拟机的克隆

第一步&#xff1a; 虚拟机右击 -> 管理 ->克隆 第二步&#xff1a; 在这一步勾选创建完整克隆&#xff0c;其他的都下一步 第三步 1.修改 mac地址 点击生成&#xff0c;就会生成一个随机的mac地址 2.修改主机名 vim /etc/hostname 修改完主机名后 reboot 重启虚拟机…

C++ STL学习之【优先级队列】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 16.11.17 文章目录 &#x1f307;前言&#x1f3d9;️正文1、优先级队列的使用1.1、基本功能1.2、优先级模式切换1.3、相关题目 2、模拟…

蛋白质界的 ChatGPT:AlphaFold1 论文必备知识,不会有人还不知道吧

你知道 AlphaFold2 吗&#xff1f;它真正解决了蛋白质三维结构预测的算法困境&#xff0c;堪称蛋白质界的 chat-GPT4&#xff0c;甚至它的意义不是 chat-GPT4 所能够匹敌的。它为世界疾病治疗药物开发以及探究生物生命之谜提供了通向天神的一条道路&#xff0c;未来是生物的世纪…

Android开机时间工具分析

背景 android 上面有很多的方法可以分析开机时间 比如打log&#xff0c;通过log 分析。android 的官网上面提供了下面的两种图形化的方式来分析开机时间&#xff0c;一些异常很明显的拖长整个开机时间的活动 可以很容易就看出来。 问题 android 官网和网上的教程很多都不适用于…

【解决方案】基于边缘视频AIBox的校园立体防控解决方案

基于边缘AIBox的校园立体防控解决方案 一、方案背景 智慧校园安全防控系统是一款围绕学校周界安全、出入口安全、人身安全、消防安全、财产安全等校园安全场景打造的主动智能预警防控系统。它利用人工智能技术对校内及周边环境进行全天候24h实时监测和智能分析&#xff0c;对…

Linux最常用的15个基本命令

目录 Linux基本命令 命令1&#xff1a;ls &#xff08;查看指定目录中有哪些内容&#xff09; ls / 相当于查看根目录中的内容&#xff0c;相当于查看我的电脑 ls -l&#xff08;小写l&#xff0c;或者使用ll&#xff09;详细查看目录下所有内容 ls /usr/lib&#xff08…

AI面试必刷算法题 附答案和解析 --持续更新中

面试中发现很多同学一股脑优化、润色项目经历&#xff0c;但聊到基本的算法&#xff0c;反而会一脸懵X&#xff0c;得空整理下算法题给大家&#xff0c;希望对你有帮助。 1. tail(head(tail(C))) ( ) 已知广义表: A(a,b), B(A,A), C(a,(b,A),B), 求下列运算的结果:&#xff08…

vue 做一个文本展示 点击文本弹出element ui的时间选择器 但不会出现element ui时间组件的那个输入框

我们先来创建一个vue2项目 引入element ui 然后 找到一个组件 这样写 <template><div><el-date-pickerv-model"value"type"datetimerange"align"right"unlink-panelsrange-separator"至"start-placeholder"开始日…

ext-3 怎么将PDK的库包添加到CCS工程中

第一次接触ccs和A8这个库&#xff0c;PDK工具包的库是啥后缀&#xff0c;怎么添加到工程里&#xff1f;等等&#xff0c;这些摸索了好久&#xff0c;这里记录一下&#xff01;&#xff08;这里的编译器都选则的是GNU&#xff0c;非TI自带的编译器&#xff09; 目录 1、问题来…

UNIX网络编程卷一 学习笔记 第十一章 名字与地址转换

到目前为止&#xff0c;本书中所有例子都用数值地址表示主机&#xff08;如206.6.226.33&#xff09;&#xff0c;用数值端口号来标识服务器&#xff08;如端口13代表daytime服务器&#xff09;。但出于某些理由&#xff0c;我们应使用名字而非数值&#xff1a;名字比较容易记住…

编译链接再认识+gdb认识+makefile了解

索引 一. 编译链接再认识1.预处理2.编译3.汇编4.链接1.静态链接2.动态链接 二.gdb三.makefile/make 一. 编译链接再认识 主要针对gcc展开 一个文件从源文件编译成可执行文件大致要经历四个步骤 预处理&#xff08;进行宏替换&#xff09;编译&#xff08;生成汇编&#xff09…

[Pandas] 创建透视表与交叉表

1.生成透视表 在使用Python处理数据时&#xff0c;我们希望能够快速地进行排列与计算数据&#xff0c;从而帮助我们更有效的分析数据&#xff0c;pivot_table函数可以实现Excel数据透视表的功能 基本语法格式 pd.pivot_table(data, valuesNone, indexNone, columnsNone, agg…

【51单片机】使用STC烧录软件生成定时器的代码以及注意事项

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Love Story】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 1.点击定时器计算器​编辑 2.每次打开的时…

华为MPLS跨域C1方式RR场景(数据不经过RR)实验配置

目录 配置BGP邻居的建立 配置MPLS LDP 配置RR之间的MP-BGP邻居 配置通过ASBR学习PE路由并为PE分配标签&#xff08;实现Vpnv4路由的传递和数据传输&#xff09; 根据图配置接口的IP地址和IGP协议 BGP邻居用来传递标签和RR、PE的路由 MP-BGP邻居用来传递Vpnv4路由 配置BG…

QGC分析(一)-整体分析和通信流程

参考QGroundControl开发指南 设计理念 QGC用户界面是用QML实现的。 构建 可以按照这一篇来在Windows中下载源码并且编译。QGroungControl在QT中源码编译&#xff08;包括配置环境&#xff09; 通信流程 src/comm/LinkManager.cc LinkManager始终打开UDP端口&#xff0c;…

Vue3中如何实现数字翻牌效果?

一、需求 监听数据的变化&#xff0c;实现数字翻牌效果 本人OS:本想截一个gif&#xff0c;但是一直没找到合适的截gif工具......有好用的截gif工具&#xff0c;跪求戳戳我~ 二、思路 1.设置初始数组&#xff1a;[0] 2. 把获取到的新数据整个数字用逗号隔开&#xff0c;组成…