如何在Qt中使用周立功USB转CAN卡

如何在 Qt 中使用周立功 USB 转 CAN 卡

文章目录

  • 如何在 Qt 中使用周立功 USB 转 CAN 卡
    • 一、简介
    • 二、准备工作
    • 三、使用
    • 四、运行效果
    • 五、写在最后

一、简介

最近在工程中用到了周立功的 USBCAN 卡,需求是要通过上位机进行通信,因此有了这篇文章。

有关 周立功 USBCAN 的内容在官网中: USB接口CAN卡-广州致远电子股份有限公司

其中有多种型号,我所使用的是 USBCAN-2E-U,如下所示:

在这里插入图片描述

上述图片来源于ZLG致远电子-广州致远电子股份有限公司,如构成侵权,请联系本人删除!!!

因此,本文是基于 USBCAN-2E-U 的开发示例,适合于有一定 Qt 经验基础的朋友!

本文开发环境如下所示:

  • USBCAN-2E-U
  • Windows 10 x64
  • Qt 5.12.3

二、准备工作

有关 USBCAN-2E-U 的文档在 USBCAN-2E-U 产品概述 中所示,首先需要安装相应的设备驱动,驱动列表链接为:驱动下载

如若点击无法跳转,可自行复制以下链接进行跳转

  • https://manual.zlg.cn/web/#/146

安装驱动过程作者在这里就不赘述了,在前面提到的 产品概述 中有相关文档,不清楚的朋友可以自行阅读。

有关库函数需要在 函数库/例程下载 中进行下载,其中还有部分例程可以做参考。

如若点击无法跳转,可自行复制以下链接进行跳转

  • https://manual.zlg.cn/web/#/152?page_id=5332

下载解压后得到如下所示文件:

在这里插入图片描述

  • zlgcan_x64:对应 64位 操作系统所使用的库文件。
  • zlgcan_x86:对应 32位 操作系统所使用的库文件。
  • 使用手册:使用手册中包含使用方法及 API 解释。

三、使用

我这里以 zlgcan_x64 进行开发!!! x86 同理。

新建 Qt 项目,我这里做了一个简单的 ui 用于后面的测试,如下所示:

在这里插入图片描述

.lib.h 文件放入工程目录(.pro 所在的目录)下,树状图如下所示:

.
|-- ZLG_CAN
|   |-- canframe.h
|   |-- config.h
|   |-- typedef.h
|   |-- zlgcan.h
|   `-- zlgcan.lib
|-- main.cpp
|-- mainwindow.cpp
|-- mainwindow.cpp.autosave
|-- mainwindow.h
|-- mainwindow.ui
|-- zlglibTest.pro
`-- zlglibTest.pro.user1 directory, 12 files

ZLG_CAN 文件夹中文件如下所示:

在这里插入图片描述

kerneldlls 文件夹和 zlgcan.dll 文件放入 debug 目录,如下图所示:

在这里插入图片描述

做好上述准备之后,导入库文件,按照如下所示操作进行:

  1. 鼠标在项目文件上右键选择 添加库:

    在这里插入图片描述

  2. 选择 外部库 后点击下一步:

    在这里插入图片描述

  3. 然后按照下图所示进行配置(库文件为 .lib ),配置完成后点击下一步即可:

    在这里插入图片描述

  4. 完成后,会出现如下界面,将在 .pro 文件中添加内容:

    在这里插入图片描述

或者也可以自行在 .pro 文件中添加如下所示的代码进行导入:

win32: LIBS += -L$$PWD/ZLG_CAN/ -lzlgcanINCLUDEPATH += $$PWD/ZLG_CAN
DEPENDPATH += $$PWD/ZLG_CAN

这里需要注意路径的问题,$$PWD 路径为 .pro 文件所在的目录。

上述两种方法用一种即可!!!效果是一样的!!!

接下来就是代码部分:

  • mainwindows.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H#include <QMainWindow>
    #include <QMessageBox>
    #include <QDateTime>
    #include <QThread>#include "zlgcan.h"namespace Ui {
    class MainWindow;
    }typedef struct {DEVICE_HANDLE _dhandle;         // 驱动设备接口CHANNEL_HANDLE _chHandle;    // 通道接口
    }zlgStruct;enum OutPutLevel
    {OUT_INFO = 0,OUT_SUCCESS,OUT_WARN,OUT_ERROR,
    };// uint8_t 数组 转 QString 十六进制
    // eg: 00 01 02 03 4F
    // upper 参数为 True 则输出大写十六进制,反之则小写
    static QString arrayToHexString(const uint8_t* pdata, uint16_t length, bool upper) {QString hexStr;QByteArray byteArray(reinterpret_cast<const char *>(pdata), length);hexStr = byteArray.toHex();if (upper)hexStr = hexStr.toUpper();for (int i = 2; i < hexStr.length(); i += 3) {hexStr.insert(i, ' ');}return hexStr;
    }class ZlgControlDev : public QObject
    {Q_OBJECTpublic:explicit ZlgControlDev(QObject *parent = nullptr);~ZlgControlDev() {if (zlgGetStatus()) {ZCAN_CloseDevice(_zlgStr._dhandle);}}void zlgEntry(void) {emit zlgControlLogSignal(QString("[ZlgControlDev::zlgEntry] threadId: 0x%1").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16).toUpper()),OUT_INFO);}void zlgConnect(void);bool zlgDisConnect(void) {if (zlgGetStatus()) {ZCAN_CloseDevice(_zlgStr._dhandle);return true;}return false;}void zlgSendData(QByteArray data);void zlgRecvData(void);bool zlgGetStatus(void) {return this->_zlgStr._dhandle == Q_NULLPTR ? false : true;}private:zlgStruct _zlgStr;signals:void zlgControlLogSignal(QString log, OutPutLevel level);void zlgConnectSignal(bool status);
    };class MainWindow : public QMainWindow
    {Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_openButton_released();void on_sendButton_released();private:Ui::MainWindow *ui;QThread* _mainThreadPtr;ZlgControlDev* _zlgDevPtr;QString praseText(QString text, OutPutLevel level){QString str;// 加入时间信息QString timeSlamp = QDateTime::currentDateTime().toString("[yyyy-MM-dd HH:mm:ss] > ");str.append(QString("<font color = blue>%1</font>").arg(timeSlamp));switch (level) {case OUT_INFO:str.append(QString("<font color = black>%1</font>").arg(text));break;case OUT_SUCCESS:str.append(QString("<font color = green>%1</font>").arg(text));break;case OUT_WARN:str.append(QString("<font color = orange>%1</font>").arg(text));break;case OUT_ERROR:str.append(QString("<font color = red>%1</font>").arg(text));}return str;}signals:void startConnectSignal(void);void startZlgRecvSignal(void);
    };#endif // MAINWINDOW_H
  • mainwindows.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
    {ui->setupUi(this);ui->textEdit->append(praseText(QString("[MainWindow::MainWindow] threadId: 0x%1").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16).toUpper()),OUT_INFO));// 注册类型qRegisterMetaType<QTextCursor>("QTextCursor");qRegisterMetaType<OutPutLevel>("OutPutLevel");qRegisterMetaType<QByteArray>("QByteArray");_mainThreadPtr = new QThread();_zlgDevPtr = new ZlgControlDev();_zlgDevPtr->moveToThread(_mainThreadPtr);connect(_mainThreadPtr, &QThread::started, _zlgDevPtr, &ZlgControlDev::zlgEntry);connect(this, &MainWindow::startConnectSignal, _zlgDevPtr, &ZlgControlDev::zlgConnect);connect(this, &MainWindow::startZlgRecvSignal, _zlgDevPtr, &ZlgControlDev::zlgRecvData);connect(_zlgDevPtr, &ZlgControlDev::zlgControlLogSignal, this, [=](QString log, OutPutLevel level) {ui->textEdit->append(praseText(log, level));}, Qt::DirectConnection);connect(_zlgDevPtr, &ZlgControlDev::zlgConnectSignal, [=](bool status) {if (!status) {ui->textEdit->append(praseText("ZLG_USB_CAN 设备连接失败!", OUT_ERROR));_mainThreadPtr->requestInterruption();_zlgDevPtr->zlgDisConnect();} else {ui->textEdit->append(praseText("ZLG_USB_CAN 设备连接成功!", OUT_SUCCESS));ui->openButton->setText("断开连接");emit startZlgRecvSignal();}});_mainThreadPtr->start();
    }MainWindow::~MainWindow()
    {_mainThreadPtr->requestInterruption();_mainThreadPtr->quit();_mainThreadPtr->wait();delete _zlgDevPtr;delete ui;
    }/*!*  @File        : mainwindow.cpp*  @Brief       : 打开/关闭 设备槽函数*  @Details     : None*  @Param       : void*  @Return      : void*  @Author      : Liu Jiahao*  @Date        : 2025-09-04 11:18:41*  @Version     : v1.1*  @Copyright   : Copyright By Liu Jiahao, All Rights Reserved**/
    void MainWindow::on_openButton_released()
    {if (!QString::compare(ui->openButton->text(), "打开设备")) {emit startConnectSignal();} else {_mainThreadPtr->requestInterruption();if (_zlgDevPtr->zlgDisConnect()) {ui->textEdit->append(praseText("ZLG_USB_CAN 设备断开连接成功!", OUT_SUCCESS));} else {ui->textEdit->append(praseText("ZLG_USB_CAN 设备断开连接失败!", OUT_ERROR));}ui->openButton->setText("打开设备");}
    }/*!*  @File        : mainwindow.cpp*  @Brief       : 模拟报文发送槽函数*  @Details     : None*  @Param       : void*  @Return      : void*  @Author      : Liu Jiahao*  @Date        : 2025-09-04 14:23:39*  @Version     : v1.1*  @Copyright   : Copyright By Liu Jiahao, All Rights Reserved**/
    void MainWindow::on_sendButton_released()
    {if (!_zlgDevPtr->zlgGetStatus()) {ui->textEdit->append(praseText("ZLG_USB_CAN 设备未打开,打开后重试!", OUT_ERROR));return;}QByteArray data;data.append(static_cast<char>(0x00));data.append(static_cast<char>(0x01));_zlgDevPtr->zlgSendData(data);
    }/*!*  @File        : mainwindow.cpp*  @Brief       : 构造函数*  @Details     : None*  @Param       : void*  @Return      : void*  @Author      : Liu Jiahao*  @Date        : 2025-09-04 14:34:20*  @Version     : v1.1*  @Copyright   : Copyright By Liu Jiahao, All Rights Reserved**/
    ZlgControlDev::ZlgControlDev(QObject *parent) :QObject(parent)
    {_zlgStr._dhandle = Q_NULLPTR;
    }/*!*  @File        : mainwindow.cpp*  @Brief       : zlg 设备连接线程入口函数*  @Details     : None*  @Param       : void*  @Return      : void*  @Author      : Liu Jiahao*  @Date        : 2025-09-04 14:35:04*  @Version     : v1.1*  @Copyright   : Copyright By Liu Jiahao, All Rights Reserved**/
    void ZlgControlDev::zlgConnect()
    {emit zlgControlLogSignal(QString("[ZlgControlDev::zlgConnect] threadId: 0x%1").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16).toUpper()),OUT_INFO);// 打开设备,获取设备句柄_zlgStr._dhandle = ZCAN_OpenDevice(ZCAN_USBCAN_2E_U, 0, 0);if (_zlgStr._dhandle == Q_NULLPTR) {emit zlgControlLogSignal("[ZCAN_OpenDevice] 打开设备失败!", OUT_ERROR);emit zlgConnectSignal(false);return;}emit zlgControlLogSignal("[ZCAN_OpenDevice] 打开设备成功!", OUT_SUCCESS);// 设置波特率if (ZCAN_SetValue(_zlgStr._dhandle,QString("0/baud_rate").toStdString().c_str(),QString("500000").toStdString().c_str()) != STATUS_OK) {emit zlgControlLogSignal("[ZCAN_SetValue] 设置波特率失败!", OUT_ERROR);emit zlgConnectSignal(false);return;}emit zlgControlLogSignal("[ZCAN_SetValue] 设置波特率成功!", OUT_SUCCESS);// 配置通道参数ZCAN_CHANNEL_INIT_CONFIG cfg;memset(&cfg, 0, sizeof(cfg));cfg.can_type        = TYPE_CAN;     // 设备为 CAN 设备cfg.can.filter      = 0;            // 双滤波cfg.can.mode        = 0;            // 正常模式cfg.can.acc_code    = 0;            // 帧过滤验收码cfg.can.acc_mask    = 0xFFFFFFFF;   // 帧过滤屏蔽码// 初始化 CAN 通道_zlgStr._chHandle = ZCAN_InitCAN(_zlgStr._dhandle,static_cast<UINT>(0),&cfg);if (_zlgStr._chHandle == Q_NULLPTR) {emit zlgControlLogSignal("[ZCAN_InitCAN] 初始化CAN通道 [0] 失败!",OUT_ERROR);emit zlgConnectSignal(false);return;}emit zlgControlLogSignal("[ZCAN_InitCAN] 初始化CAN通道 [0] 成功!",OUT_SUCCESS);// 启动通道if (ZCAN_StartCAN(_zlgStr._chHandle) != STATUS_OK) {emit zlgControlLogSignal("[ZCAN_StartCAN] 启用CAN通道 [0] 失败!",OUT_ERROR);emit zlgConnectSignal(false);return;}emit zlgControlLogSignal("[ZCAN_StartCAN] 启用CAN通道 [0] 成功!",OUT_SUCCESS);emit zlgConnectSignal(true);
    }/*!*  @File        : mainwindow.cpp*  @Brief       : zlg 接收数据函数*  @Details     : None*  @Param       : void*  @Return      : void*  @Author      : Liu Jiahao*  @Date        : 2025-09-04 15:54:59*  @Version     : v1.1*  @Copyright   : Copyright By Liu Jiahao, All Rights Reserved**/
    void ZlgControlDev::zlgRecvData()
    {if (!zlgGetStatus()) {return;}emit zlgControlLogSignal(QString("[ZlgControlDev::zlgRecvData] threadId: 0x%1 start!!!").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16).toUpper()),OUT_INFO);while(!QThread::currentThread()->isInterruptionRequested()) {/* 获取收到的报文数(确保缓冲区有数据) */uint32_t size = ZCAN_GetReceiveNum(this->_zlgStr._chHandle, 0);if (size) {ZCAN_Receive_Data recvData;/* 接收数据 */ZCAN_Receive(this->_zlgStr._chHandle, &recvData, 1);QString logStr("[ZlgControlDev::zlgRecvData] %1 %2 %3x Rx d %4 %5");QString hexStr = arrayToHexString(reinterpret_cast<const uint8_t*>(&recvData.frame.data[0]), static_cast<uint16_t>(recvData.frame.can_dlc), false);logStr = logStr.arg(recvData.timestamp).arg(1).arg(QString::number(static_cast<uint32_t>(recvData.frame.can_id) & static_cast<uint32_t>(0x1FFFFFFF), 16)).arg(recvData.frame.can_dlc).arg(hexStr);emit zlgControlLogSignal(logStr,OUT_INFO);}QThread::msleep(10); // 延迟 10ms}emit zlgControlLogSignal(QString("[ZlgControlDev::zlgRecvData] threadId: 0x%1 end!!!").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16).toUpper()),OUT_INFO);
    }/*!*  @File        : mainwindow.cpp*  @Brief       : None*  @Details     : None*  @Param       : void*  @Return      : void*  @Author      : Liu Jiahao*  @Date        : 2025-09-04 15:52:29*  @Version     : v1.1*  @Copyright   : Copyright By Liu Jiahao, All Rights Reserved**/
    void ZlgControlDev::zlgSendData(QByteArray data)
    {if (!zlgGetStatus())return;emit zlgControlLogSignal(QString("[ZlgControlDev::zlgSendData] threadId: 0x%1").arg(QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId()), 16).toUpper()),OUT_INFO);ZCAN_Transmit_Data frame;memset(&frame, 0, sizeof(frame));// 写入数据frame.transmit_type = 2;frame.frame.can_id = static_cast<canid_t>(0x51801);frame.frame.can_dlc = static_cast<BYTE>(data.size());for (int index = 0; index < data.size(); index++) {frame.frame.data[index] = static_cast<BYTE>(data.at(index));}// 发送数据UINT ret = ZCAN_Transmit(this->_zlgStr._chHandle, &frame, 1);if (ret != STATUS_OK){emit zlgControlLogSignal("通道 [0] 发送报文失败!", OUT_ERROR);return;}emit zlgControlLogSignal("通道 [0] 发送报文成功!", OUT_SUCCESS);
    }

大致思路就是,开启一个线程用于接收数据,发送与接收不能在同一个线程中,理由很简单,接收线程一直在 while 循环,则无法继续操作这个线程。其实也可以把发送单独放一个线程中,这里我就不做过多赘述,代码仅供参考,实现方式多样,可自行斟酌。

值得注意的是,我在发送数据的时候,设置 frame.transmit_type = 2; 其含义在 zlg 官方 API 文档中也有描述:

在这里插入图片描述

具体解释还请查看 API 文档。


四、运行效果

软件运行起来之后效果如下所示:

在这里插入图片描述


五、写在最后

本文介绍了 如何在 Qt 中使用 周立功 USBCAN

欢迎广大读者提出问题以及修改意见,本人看到后会给予回应,欢迎留言,后续会逐步进行开源!!!
另外,由于文章是作者手打的文字,有些地方可能文字会出错,望谅解,也可私信联系我,我对其进行更改。

  • 个人CSDN账号:刘梓谦_-CSDN博客

  • Gitee:刘佳豪 (liu-jiahaohappy) - Gitee.com

  • GitHub:Jiahao-Liu29 (github.com)

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

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

相关文章

JavaScript 源码剖析:从字节码到执行的奇妙旅程

JavaScript&#xff0c;这门风靡全球的脚本语言&#xff0c;以其灵活性和跨平台性征服了无数开发者。我们每天都在使用它&#xff0c;但它在后台是如何工作的&#xff1f;一段看似简单的JS代码&#xff0c;在执行之前究竟经历了哪些“变形记”&#xff1f;今天&#xff0c;让我…

FPGA—硬件电路一旦上电配置完成,各个功能模块会并行地持续工作

1.示例代码参考这段代码是用 Verilog 编写的一个 LED 闪烁控制模块&#xff0c;主要实现了 LED 按一定时间间隔循环移位闪烁的功能。下面详细解释其架构组成&#xff1a;模块定义与端口声明模块名为 led_flash&#xff0c;包含三个端口&#xff1a;sys_clk&#xff1a;输入端口…

从零到上线:Docker、Docker Compose 与 Runtime 安装部署全指南(含实战示例与应用场景)

文章目录一、Docker 安装1. Ubuntu / Debian&#xff08;官方仓库&#xff09;2. RHEL / CentOS / Rocky / AlmaLinux3. 验证4. macOS / Windows&#xff08;Docker Desktop&#xff09;二、Docker Compose&#xff08;V2&#xff09;安装与基本用法1) 验证2) 最小示例&#xf…

Java基础篇02:基本语法

1 注释 注释是写在程序中对代码进行解释说明的文字&#xff0c;方便自己和其他人查看&#xff0c;以便理解程序的。注释分为三种&#xff1a;单行注释、多行注释、文档注释注释不影响代码的执行&#xff1a; 原因是编译后的文件已经没有注释了// 这是单行注释&#xff1a;。通常…

【SECS/GEM 】SECS/GEM 日志管理相关的消息

明白 ✅ 在 SECS/GEM 架构里&#xff0c;设备日志&#xff08;Equipment Logging 主要涉及 事件日志&#xff08;Event Log&#xff09;、报警日志&#xff08;Alarm Log&#xff09;、配方操作日志&#xff08;Recipe Log&#xff09;、以及用户操作/命令日志。这些日志通过 S…

ragas 框架使用Chat-GLM模型报API 调用参数有误,请检查文档

ragas 框架使用Chat-GLM模型报API 调用参数有误&#xff0c;请检查文档解决方案 from ragas.llms import LangchainLLMWrapper # 点击LangchainLLMWrapper 进入这个类找到这个方法直接 return 0.1出现问题原因 ChatGLM 不支持设置temperature等于0&#xff0c;默认的值太小了

Kaggle - LLM Science Exam 大模型做科学选择题

Kaggle - LLM Science Exam Science Exam Simple Approach w/ Model Hub | Kaggle Platypus2-70B with Wikipedia RAG | Kaggle 5个选项只有一个选项正确&#xff0c;目标&#xff1a;回答一个选项序列&#xff08;只有前三个有效&#xff09; 输出正确选项 &#xff08;可…

贪吃蛇鱼小游戏抖音快手微信小程序看广告流量主开源

核心优势&#xff1a;为流量主运营者与新手量身打造 1. 为流量主运营者破解成本困局 本地化运行&#xff0c;零服务器成本&#xff1a;数据运行与存储全程在用户手机本地完成&#xff0c;无需部署服务器及后台系统&#xff0c;彻底摆脱服务器租赁、维护等硬性支出&#xff0c;…

PDF Reader 编辑阅读工具(Mac中文)

原文地址&#xff1a;PDF Reader 编辑阅读 for Mac v5.2.0 PDF Reader Pro Mac&#xff0c;是一款PDF编辑阅读&#xff0c;PDF Reader Pro让您直接在 Mac 上进行PDF文件阅读、笔记、编辑、转换、创建PDF、签署PDFs、填写PDF Forms表单、设置密码、合并拆分文件、水印等等&…

Django REST framework:SimpleRouter 使用指南

1. SimpleRouter 是什么&#xff1f; SimpleRouter 是 DRF&#xff08;Django REST framework&#xff09;提供的路由器&#xff0c;能根据 ViewSet 自动生成标准的 REST 路由&#xff0c;包括&#xff1a; GET /resources/ → 列表&#xff08;list&#xff09;POST /resource…

覆盖Transformer、GAN:掩码重建正在重塑时间序列领域!

随着大数据与深度学习的发展&#xff0c;时间序列分析的建模能力显著提升&#xff0c;而掩码重建作为一种自监督学习范式&#xff0c;已成为提升序列表征能力的重要技术。该方法通过随机掩码部分数据并重建原始序列&#xff0c;迫使模型挖掘时序依赖性与潜在模式&#xff0c;在…

用AI做TikTok影视解说,全流程全自动成片,不懂外语也能做全球矩阵!

多语种解说&#xff1a; 短剧出海狂吸美金 多语种解说抢先机 TikTok、YouTube等平台&#xff0c;尤其在非英语市场&#xff0c;内容供给仍远远不足&#xff0c;每一个小语种市场都是潜在蓝海。 有人用英语讲仙侠、西语讲爽剧、日语讲宫斗、阿语讲悬疑&#xff0c;一夜涨粉百…

解密大语言模型推理:输入处理背后的数学与工程实践

解密大语言模型推理&#xff1a;输入处理背后的数学与工程实践当你向ChatGPT提问时&#xff0c;短短几秒内就能获得流畅的回答&#xff0c;这背后隐藏着怎样的技术魔法&#xff1f;答案在于大语言模型高效推理过程中精妙的输入处理机制。在现代大语言模型推理中&#xff0c;输入…

02、连接服务器的几种方式

02、连接服务器的几种方式 1、Xshell 适用于Windows https://www.xshell.com/en/free-for-home-school/ 2、Termius 适用于MacOS 直接苹果商店下载即可 3、IDEA 连接 Tools - Deployment - Browse Remote Host 1、打开Browse Remote Host2、添加服务3、输入服务器连接信息并测试…

高并发系统设计方案(直播场景)

最近在准备面试&#xff0c;正把平时积累的笔记、项目中遇到的问题与解决方案、对核心原理的理解&#xff0c;以及高频业务场景的应对策略系统梳理一遍&#xff0c;既能加深记忆&#xff0c;也能让知识体系更扎实&#xff0c;供大家参考&#xff0c;欢迎讨论。 1. 微服务拆分 …

网络编程基础:一文搞懂 Socket、HTTP、HTTPS、TCP/IP、SSL 的关系

在日常开发中&#xff0c;我们经常听到 Socket、HTTP、HTTPS、TCP/IP、SSL 这些术语&#xff0c;这些概念往往容易混淆&#xff0c;且让人感到困惑。本文将用最通俗易懂的方式来讲清这些网络概念及其相互关系。一、从寄信说起&#xff1a;网络通信的本质假如你要给远方的朋友寄…

查看LoRA 哪个适配器处于激活状态(67)

哪个适配器处于激活状态 当前哪个适配器处于激活状态?我们来查看active_adapter属性就知道了 peft_model.active_adapter输出 default试试另一个(适配器) 你更想试试另一个(适配器)吗?只需调用set_adapter()方法即可。 peft_model.set_adapter(yoda) peft_model.act…

​​Nginx高性能Web服务器实战:从协议原理到运维优化​​

目录 前言 一、Web基础概念 1.1 什么是Web&#xff1f; 1.2 B/S架构模型 1.3 Web请求与响应流程 1.4 静态资源 vs 动态资源 二、HTTP/HTTPS协议详解 2.1 HTTP与HTTPS区别 2.2 HTTPS握手流程 2.3 HTTP状态码大全 三、Nginx核心知识 3.1 Nginx简介 3.2 Nginx vs Apache 3.3 Nginx…

【先楫HPM5E00_EVK系列-板卡测评3】hpm5e00evk平台中断、定时器、PWM、USART等基础功能详解

此文介绍了利用先楫半导体&#xff08;hpm&#xff09;官方hpm5e00_evk开发板使用的主控芯片的一些原理性知识&#xff0c;无实验内容展示&#xff0c;主要汇总了先楫半导体hpm5e00主控芯片的中断、定时器、pwm、usart等功能&#xff0c;主要内容来源于B站“HPM_FAE”的视频和官…

golang 依赖管理

目录 演进过程 1. GOPATH 阶段&#xff08;Go 1.0 - 1.10&#xff0c;2012 - 2018&#xff09; 2. Vendor 机制阶段&#xff08;Go 1.5 实验性引入&#xff0c;1.6 正式支持&#xff0c;2015 - 2018&#xff09; 3. Go Modules 过渡期&#xff08;Go 1.11 - 1.16&#xff0…