当前位置: 首页 > news >正文

【HAL库】STM32CubeMX开发----STM32F407----LAN8720A----移植FreeModbus实现ModbusTCP


前言

本次实验以 STM32F407VET6 芯片为MCU,使用 25MHz 外部时钟源。
以太网PHY层芯片为 LAN8720A,移植FreeModbus实现ModbusTCP网口通信。
具体内容参考文章:【HAL库】STM32CubeMX开发----STM32F407----ETH+LAN8720A+LWIP----ping通

本次移植FreeModbus中的TCP功能,做客户端(从机),实现网口TCP-Modbus通信。

一、FreeModbus源码下载

FreeModbus源码下载链接:https://www.embedded-experts.at/en/freemodbus-downloads/

点击下载
在这里插入图片描述

源码压缩包如下:

在这里插入图片描述

二、移植FreeModbus源码----新建TCP功能文件

本次实验,要实现FreeModbus的TCP功能,新建一个 FreeModbus_TCP 文件夹,将需要的文件都移植,具体文件移植如下:

步骤1

打开 freemodbus-v1.6 文件夹,点击 modbus 文件夹。

在这里插入图片描述

步骤2

modbus 文件夹中的全部文件移植到新建的 FreeModbus_TCP 文件夹中。
在这里插入图片描述

步骤3

freemodbus-v1.6\demo\STR71XTCP中的 port 文件,移植到新建的 FreeModbus_TCP 文件夹中。

在这里插入图片描述

步骤4

移植最终结果,新建的 FreeModbus_TCP 文件夹内容如下:

在这里插入图片描述

三、移植FreeModbus源码----TCP功能文件 移植 到STM32工程文件中。

本次使用的是能够实现以太网ping通的STM32F407工程。
工程源码:STM32F407-ETH+LAN8720A+LWIP-无操作系统-ping通----程序源码

步骤1

FreeModbus_TCP 文件夹复制到工程文件中。

在这里插入图片描述

步骤2

使用keil5打开工程,将FreeModbus_TCP 文件夹中的文件导入。

在这里插入图片描述

选择FreeModbus_TCP 文件夹中的 functions 文件夹的全部.c文件。

在这里插入图片描述

选择FreeModbus_TCP 文件夹中的 port 文件夹的全部.c文件。

在这里插入图片描述
选择FreeModbus_TCP 文件夹中的 tcp 文件夹的全部.c文件。
在这里插入图片描述
选择FreeModbus_TCP 文件夹中的mb.c文件。
在这里插入图片描述

最终结果如下

在这里插入图片描述
在这里插入图片描述

步骤3

点击魔法棒,选择 C/C++,添加文件路径

在这里插入图片描述

添加文件路径

在这里插入图片描述

添加结果如下

在这里插入图片描述
编译程序,会出现一些错误,下面编辑程序,消除错误。

四、移植FreeModbus源码----编辑程序

步骤1:修改 mbconfig.h

关闭 MB_ASCII 和 MB_RTU,打开 MB_TCP

在这里插入图片描述

步骤2:修改 port.h

将27行:#include “71x_type.h” 注释掉。
将39行到46行的注释,打开。
具体代码如下:

在这里插入图片描述

步骤3:修改 portevent.c

将以下程序,替换原来的程序。

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"/* ----------------------- Variables ----------------------------------------*/
static eMBEventType eQueuedEvent;
static BOOL     xEventInQueue;/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortEventInit( void )
{xEventInQueue = FALSE;return TRUE;
}BOOL
xMBPortEventPost( eMBEventType eEvent )
{xEventInQueue = TRUE;eQueuedEvent = eEvent;return TRUE;
}BOOL
xMBPortEventGet( eMBEventType * eEvent )
{BOOL            xEventHappened = FALSE;if( xEventInQueue ){*eEvent = eQueuedEvent;xEventInQueue = FALSE;xEventHappened = TRUE;}return xEventHappened;
}

步骤4:修改 porttcp.c

在24行,添加 #include “string.h”
在43行,添加 #define NETCONN_COPY 0x01

在这里插入图片描述

将120行和135行的 vPortEnterCritical( );,注释掉。

在这里插入图片描述
将148行的 vMBPortEventClose( ); 注释掉。
在这里插入图片描述

步骤5:修改 mb.c

将232行的 ENTER_CRITICAL_SECTION( );,注释掉。
将261行的 EXIT_CRITICAL_SECTION( );,注释掉。

在这里插入图片描述

步骤6:新建文件

User_modbus_TCP.c文件

#include <stdio.h>
#include <string.h>
#include "User_modbus_TCP.h"
#include "mb.h"
#include "mbutils.h"void ModbusTCPInit(void)
{eMBTCPInit(MODBUS_TCP_PORT);eMBEnable();
}void ModbusTCPDeInit(void)
{eMBDisable();eMBClose();
}void ModbusTCPMain(void)
{if (MB_ENOERR != eMBPoll()){ModbusTCPDeInit();ModbusTCPInit();}
}//线圈
#define REG_Coils_START   1
#define REG_Coils_SIZE    10uint8_t  Coils_Data[REG_Coils_SIZE] = {1,1,0,1,0,0,1,1,1,0};/*** @brief: 读线圈---01,写线圈---05** @param pucRegBuffer  缓存指针* @param usAddress     起始地址* @param usNCoils      线圈数量* @param eMode         读写模式* @return eMBErrorCode 错误码*/
eMBErrorCode eMBRegCoilsCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode)
{uint16_t i = 0,byteOffset=0,bitOffset=0,RegIndex = usAddress - REG_Coils_START-1;if ((usAddress >= REG_Coils_START)&&(usAddress + usNCoils <= REG_Coils_START + REG_Coils_SIZE+1)){if (MB_REG_READ == eMode){for(i=0;i<usNCoils;i++){byteOffset = i / 8;bitOffset = i % 8;xMBUtilSetBits(&pucRegBuffer[byteOffset], bitOffset, 1, Coils_Data[RegIndex+i]);}}else{for(i=0;i<usNCoils;i++){byteOffset = i / 8;bitOffset = i % 8;Coils_Data[RegIndex+i]=xMBUtilGetBits(&pucRegBuffer[byteOffset], bitOffset, 1);}}}else{return MB_ENOREG;}return MB_ENOERR;
}//离散寄存器
#define REG_DISCRETE_START   10
#define REG_DISCRETE_SIZE    20uint8_t  Discrete_Data[REG_DISCRETE_SIZE] = {1,1,0,1,0,0,1,1,1,0,1,0,0,1};/*** @brief:读离散寄存器---02** @param pucRegBuffer  缓存指针* @param usAddress     起始地址* @param usNDiscrete   寄存器个数* @return eMBErrorCode 返回错误码*/
eMBErrorCode eMBRegDiscreteCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNDiscrete)
{uint16_t i = 0,byteOffset=0,bitOffset=0,RegIndex = usAddress - REG_DISCRETE_START-1;if ((usAddress >= REG_DISCRETE_START)&&(usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISCRETE_SIZE+1)){for(i=0;i<usNDiscrete;i++){byteOffset = i / 8;bitOffset = i % 8;xMBUtilSetBits(&pucRegBuffer[byteOffset], bitOffset, 1, Discrete_Data[RegIndex+i]);}}else{return MB_ENOREG;}return MB_ENOERR;
}//保持寄存器
#define REG_HOLDING_REGISTER_START   10
#define REG_HOLDING_REGISTER_SIZE    30uint16_t  Holding_Data[REG_HOLDING_REGISTER_SIZE] = 
{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12};/*** @brief: 读保持寄存器---03,写保持寄存器---06** @param pucRegBuffer  缓存指针* @param usAddress     起始地址* @param usNRegs       寄存器个数* @param eMode         读写模式* @return eMBErrorCode 返回错误码*/eMBErrorCode eMBRegHoldingCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode)
{uint16_t i = 0,RegIndex = usAddress - REG_HOLDING_REGISTER_START-1;if ((usAddress >= REG_HOLDING_REGISTER_START )&&(usAddress + usNRegs <= REG_HOLDING_REGISTER_START  + REG_HOLDING_REGISTER_SIZE+1)){if (MB_REG_READ == eMode)//读{for(i=0;i<usNRegs;i++){pucRegBuffer[i*2] = (UCHAR)(Holding_Data[RegIndex+i]>>8);pucRegBuffer[i*2+1] = (UCHAR)Holding_Data[RegIndex+i];}}else//写{for(i=0;i<usNRegs;i++){Holding_Data[RegIndex+i]=(pucRegBuffer[i*2]<<8)|(pucRegBuffer[i*2+1]);}}}else{return MB_ENOREG;}return MB_ENOERR;
}//输入寄存器
#define REG_INPUT_REGISTER_START    1
#define REG_INPUT_REGISTER_SIZE    20uint16_t  Input_Data[REG_DISCRETE_SIZE] = 
{100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119};
/*** @brief: 读输入寄存器---04** @param pucRegBuffer  缓存指针* @param usAddress     起始地址* @param usNRegs       寄存器个数* @return eMBErrorCode 返回错误码*/
eMBErrorCode eMBRegInputCB(UCHAR *pucRegBuffer, USHORT usAddress, USHORT usNRegs)
{uint16_t i = 0,RegIndex = usAddress - REG_INPUT_REGISTER_START-1;if ((usAddress >= REG_INPUT_REGISTER_START)&&(usAddress + usNRegs <= REG_INPUT_REGISTER_START + REG_INPUT_REGISTER_SIZE+1)){for(i=0;i<usNRegs;i++){pucRegBuffer[i*2] = (UCHAR)(Input_Data[RegIndex+i]>>8);pucRegBuffer[i*2+1] = (UCHAR)Input_Data[RegIndex+i];}}else{return MB_ENOREG;}return MB_ENOERR;
}/**********************printf重定向****************************/
//取消ARM的半主机工作模式
#pragma import(__use_no_semihosting)//标准库需要的支持函数                 
struct __FILE 
{ int handle; 
}; 
FILE __stdout;       
void _sys_exit(int x) //定义_sys_exit()以避免使用半主机模式
{ x = x; 
} int fputc(int ch, FILE *f)
{  return ch;
}

需要加上printf重定向(关于printf重定向的文章),不加上,程序就会卡死,我也不知道什么原因,有哪位大神知道,可以评论说一下,非常感谢。

User_modbus_TCP.h文件

#ifndef __User_modbbus_TCP_H__
#define	__User_modbbus_TCP_H__#include "main.h"#define MODBUS_TCP_PORT 4002extern void ModbusTCPInit(void);
extern void ModbusTCPMain(void);#endif

步骤7:在主函数中调用ModbusTCP

在主函数初始化中,调用 ModbusTCPInit();
在主函数while运行中,调用 ModbusTCPMain();

在这里插入图片描述

五、移植FreeModbus源码----测试验证

使用 Modbus Poll 软件,测试 ModbusTCP 功能。
Modbus Poll 软件----下载和安装

步骤1:打开Modbus Poll 软件

在这里插入图片描述

步骤2:打开连接配置窗口,配置连接

点击菜单栏"Connection"->“Connect…”(或者按快捷键F3)弹出连接配置窗口。

在这里插入图片描述
选择 ModbusTCP/IP,然后配置IP地址,然后选择端口,其他时间都是默认值,然后点击 OK

在这里插入图片描述

步骤3:配置窗口信息

点击"Setup"->“Read/Write Definition…”,或者按快捷键F8。

在这里插入图片描述

设置从机地址,功能码,起始地址,寄存器数量等信息,然后点击OK。

在这里插入图片描述

步骤4:测试结果

功能码 01,读取线圈,测试结果与程序一致。

在这里插入图片描述

功能码 02,读取离散寄存器,测试结果与程序一致。

在这里插入图片描述

功能码 03,读取保持寄存器,测试结果与程序一致。

在这里插入图片描述

功能码 04,读取输入寄存器,测试结果与程序一致。

在这里插入图片描述


相关文章:

【HAL库】STM32CubeMX开发----STM32F407----LAN8720A----移植FreeModbus实现ModbusTCP

前言 本次实验以 STM32F407VET6 芯片为MCU&#xff0c;使用 25MHz 外部时钟源。 以太网PHY层芯片为 LAN8720A&#xff0c;移植FreeModbus实现ModbusTCP网口通信。 具体内容参考文章&#xff1a;【HAL库】STM32CubeMX开发----STM32F407----ETHLAN8720ALWIP----ping通 本次移植…...

11-矩阵(matrix)_方阵_对称阵_单位阵_对角阵

矩阵及其运算 [ a 11 ⋯ a 1 n ⋯ ⋯ ⋯ a m 1 ⋯ a m n ] \begin{bmatrix} a_{11} & \cdots & a_{1n} \\ \cdots & \cdots & \cdots \\ a_{m1} & \cdots & a_{mn} \\ \end{bmatrix} ​a11​⋯am1​​⋯⋯⋯​a1n​⋯amn​​ ​ 矩阵就是二维数组&…...

AWS多账户单点登录 IAM Identity Center(AWS SSO)

需求场景 多个aws账户&#xff0c;登陆麻烦且不安全&#xff0c;SSO单点功能并且外部身份提供者 — 如果您要管理外部身份提供者&#xff08;IdP&#xff09;&#xff08;例如 Okta 或 Active Directory&#xff09;中的用户。 官方文档&#xff1a;https://docs.aws.amazon.c…...

实验2-3-3 求奇数分之一序列前N项和 (15 分)

实验2-3-3 求奇数分之一序列前N项和 &#xff08;15 分&#xff09; 本题要求编写程序&#xff0c;计算序列 1 1/3 1/5 … 的前N项之和。 输入格式: 输入在一行中给出一个正整数N。 输出格式: 在一行中按照“sum S”的格式输出部分和的值S&#xff0c;精确到小数点后6位。…...

关于Android studio中的自动化测试脚本UiAutomator框架以及UiAutomatorViewer工具的使用——项目案例

加入依赖 implementation androidx.test.uiautomator:uiautomator:2.2.0创建CalcActivity页 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"...

OA办公自动化系统设计与实现(论文+源码)_kaic

摘要 随着信息化建设的日益深入&#xff0c;无论是政府还是企事业单位&#xff0c;部门之间的信息沟通与协调工作越来越重要。人们迫切需要一个能充分利用网络优势&#xff0c;并可以管理企业的各种重要信息的软件平台&#xff0c;利用该平台快速建立自己的信息网络和办公管理系…...

ansible——playbook

playbook playbook是剧本的意思 通过 task 调用 ansible 的模块将多个 play 组织在一 个playbook中运行。 playbook本身由以下各部分组成&#xff1a; Tasks: 任务&#xff0c;即调用模块完成的某操作 Variables: 变量 Templates: 模板 Handlers: 处理器&#xff0c;当某条件…...

DDS中间件设计

OpenDDS、FastDDS数据分发服务中间件设计 软件架构 应用层DDS层RTPS层传输层 软件层次 FastDDS整体架构如下&#xff0c;这里可以看到DDS和RTPS的关系。另外缺少一部分IDL&#xff08;统一描述语言&#xff09;&#xff0c;其应该是Pub、Sub的反序列化、序列化工具。 在RT…...

aws的EC2云服务器自己操作记录

亚马逊官网有免费试用1年的服务器 以下内容参考 1. 启动生成实例 1.1 创建实例时需要生成 使用的默认的 Debian 和 一个.pem后缀的秘钥 1.2 网上下一个Mobaxterm ,实例名是公有 IPv4 DNS 地址 ,使用SSH连接,登录名是admin 1.3 登录进去后 输入用户名 admin 后进去,sudo …...

基本ACL 和高级ACL配置

基本ACL 一、要求 1.全网可达 2.在1的基础上使PC1不能访问PC2 二、思路 1.通过写静态的方式使全网可达 2.配置acl主要是拒绝源IP的访问 3.在靠近目标的地方配置acl及使用 三、操作配置 1.IP及静态配置 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 123.0.0.1 24 [r…...

【uniapp 报错 Cannot read properties of null (reading ‘offsetWidth‘)解决办法】

该错误通常是由于访问了一个空值的offsetWidth而引起的。解决方法如下&#xff1a; 检查代码中是否有访问了空值的情况&#xff0c;比如变量未初始化或者传入了空值参数或者事件未定义。 在操作元素之前&#xff0c;确保元素已经被正确加载。可以使用如下方法&#xff1a; <…...

6.s081/6.1810(Fall 2022)Lab2: System calls

文章目录 前言其他篇章参考链接0. 前置准备1. System call tracing (moderate)1.1 简单分析1.2 Hint 11.3 Hint 21.4 Hint 31.5 Hint 41.6 Hint 51.7 测试 2. Sysinfo (moderate)2.1 声明2.2 实现2.2.1 框架2.2.2 用户态与内核态交互2.2.3 计算空闲内存的大小2.2.4 计算非UNUSE…...

Git在VSCode中的使用

1.Git图像化界面进行项目初始化&#xff08;git init&#xff09; 2. Git图形化界面对文件进行操作 当我们创建一个文件时&#xff0c;该文件后面有一个U&#xff0c;表示文件未跟踪。 我们在管理工具中输入日志并提交代码&#xff0c;相当于做了两件事&#xff0c;将文件由“…...

【双指针_移动零_C++】

题目解析 移动零 nums [0,1,0,3,12] [1,3,12,0,0]算法原理 数组划分&#xff08;数组分块&#xff09; 双指针算法&#xff08;利用数组下标来充当指针&#xff09;使用两个指针的作用&#xff1a; cur指针&#xff1a;从左往右扫描数组&#xff0c;就是遍历数组。 dest指针…...

【网络安全】网络安全威胁实时地图 - 2023

文章目录 [TOC] ① 360 安全大脑360 APT全景雷达 ② 瑞星杀毒瑞星云安全瑞星网络威胁态势感知平台 ③ 比特梵德 Bitdefender④ 飞塔防火墙 FortiGuard⑤ 音墙网络 Sonicwall⑥ 捷邦 Check Point⑦ AO卡巴斯基实验室全球模拟隧道模拟 ⑧ 数字攻击地图⑨ Threatbutt互联网黑客攻击…...

视频过大如何压缩变小?文件压缩技巧分享

如何压缩视频是许多视频编辑者、视频上传者经常遇到的问题&#xff0c;如果你也遇到了这个问题&#xff0c;不用担心&#xff0c;下面将就给大家分享几个视频压缩方法&#xff0c;可以帮助大家轻松地压缩视频&#xff0c;同时保持视频的高清晰度和音频质量。 一、嗨格式压缩大师…...

组合模式(Composite)

组合模式是一种结构型设计模式&#xff0c;主要用来将多个对象组织成树形结构以表示“部分-整体”的层次结构&#xff0c;因此该模式也称为“部分-整体”模式。简言之&#xff0c;组合模式就是用来将一组对象组合成树状结构&#xff0c;并且能像使用独立对象一样使用它们。 Co…...

grid map学习笔记3之详解grid_map_pcl库实现point cloud点云转换成grid map栅格地图

文章目录 0 引言1 grid_map_pcl示例1.1 主要文件1.2 示例数据1.3 启动文件1.4 配置文件1.5 主要实现流程1.6 启动示例1.7 示例结果 2 D435i 点云生成栅格地图2.1 D435i 点云文件2.2 修改启动文件2.3 测试和结果2.4 修改配置文件2.5 重新测试和结果 0 引言 grid map学习笔记1已…...

ebpf开发问题汇总

不同Programs之间通信 用bpf_obj_get来获取MAP的描述符&#xff0c;然后用bpf_map_reuse_fd函数来在不同program之间复用 kernel 与 user space之间 需要pin the BPF MAP to the BPF Virtual File System (VFS),来持久化存储&#xff0c;否则如果map用不到会被destory 引用…...

认识 mysql 命令

文章目录 1.简介2.选项3.子命令4.小结参考文献 1.简介 mysql 是 MySQL 的命令行客户端工具&#xff0c;用于连接到 MySQL 服务器并执行 SQL 语句。 它支持交互式和非交互式两种使用方式。以交互方式使用时&#xff0c;查询结果以 ASCII 表格式呈现。 当以非交互方式使用时&am…...

Claude Opus 4.7:一个有诚意但不完美的升级

视觉能力提升3倍、编程能力碾压GPT-5.4&#xff0c;却被用户吐槽"更费token、爱道歉、会撒谎"——Opus 4.7的真实面貌&#xff0c;比跑分更复杂。 深夜收到的推送 4月17日深夜&#xff0c;我收到这么一条消息&#xff1a; “Claude Opus 4.7已全面可用&#xff0c;编…...

Kotlin动态生成代码的实践之旅

在开发过程中,经常会遇到需要根据外部模块的类型生成特定代码的情况。今天我们来探讨如何使用Kotlin来实现这种需求,尤其是在模块间缺乏直接依赖的情况下。 背景介绍 假设我们有一个项目结构如下: |- Base | |- interface ContentProvider | |- First | |- interface Fir…...

ESP32 OTA升级避坑指南:从分区表配置到固件校验失败的常见错误全解析

ESP32 OTA升级实战排雷手册&#xff1a;7类典型错误与深度修复方案 当你盯着串口调试终端里闪烁的红色错误日志时&#xff0c;那种挫败感我深有体会。ESP32的OTA升级本应是物联网设备维护的利器&#xff0c;却在实践中成为不少开发者的噩梦。不同于基础教程的按部就班&#xff…...

告别BasicTeX的烦恼:我在M1 Mac上迁移到原生ARM版MacTeX的真实体验与避坑指南

告别BasicTeX的烦恼&#xff1a;我在M1 Mac上迁移到原生ARM版MacTeX的真实体验与避坑指南 第一次在M1 MacBook Air上安装BasicTeX时&#xff0c;我以为找到了轻量高效的LaTeX解决方案。直到连续三天被各种缺失宏包和权限问题折磨到凌晨两点&#xff0c;才意识到自己掉进了&quo…...

Colab进阶指南:解锁免费GPU,高效部署你的Keras与PyTorch项目

1. 为什么你需要Colab的免费GPU&#xff1f; 如果你正在学习深度学习或者从事AI项目开发&#xff0c;肯定对GPU的重要性深有体会。传统CPU训练一个简单的图像分类模型可能需要几个小时甚至几天&#xff0c;而一块普通的GPU可能只需要几分钟。但问题是&#xff0c;高性能GPU价格…...

国民技术 N32G430F8S7 TSSOP-20 单片机

关键特性 内核CPU -32位ARMCortex-M4 内核FPU&#xff0c;支持DSP指令 一内置1KB指令Cache缓存&#xff0c;支持Flash加速单元执行程序0等待 一 最高主频128MHz&#xff0c;160DMIPS 加密存储器 高达64KByte片内Flash&#xff0c;支持加密存储、分区管理及数据保护&#xff0c;…...

3个关键步骤掌握专业PDF文档翻译:BabelDOC让学术论文翻译不再困难

3个关键步骤掌握专业PDF文档翻译&#xff1a;BabelDOC让学术论文翻译不再困难 【免费下载链接】BabelDOC Yet Another Document Translator 项目地址: https://gitcode.com/GitHub_Trending/ba/BabelDOC 还在为复杂的学术论文翻译而烦恼吗&#xff1f;BabelDOC是一款革命…...

Linux I-O 模型深入理解

Linux I/O 模型深入理解&#xff1a;解锁高性能的关键 在当今高并发的网络环境中&#xff0c;Linux系统的I/O模型是支撑高性能服务的核心机制之一。无论是Web服务器、数据库还是实时通信系统&#xff0c;其底层I/O处理效率直接决定了系统的吞吐量和响应速度。理解Linux I/O模型…...

黄仁勋可能开始焦虑了

只做卖铲人&#xff0c;已经不能让 Nvidia 高枕无虞了。 2026年4月15日&#xff0c;黄仁勋在Dwarkesh Patel 的播客里经历了一场他很久没经历过的尖锐追问。一个多小时的对话&#xff0c;他反复用来定义英伟达的那句话是&#xff1a;“必须有东西把电子变成token。”他把自家公…...

PyTorch 2.6 镜像使用全攻略:Jupyter和SSH任你选

PyTorch 2.6 镜像使用全攻略&#xff1a;Jupyter和SSH任你选 1. 镜像简介与环境准备 PyTorch 2.6镜像是一个开箱即用的深度学习开发环境&#xff0c;预装了PyTorch 2.6框架和CUDA工具包&#xff0c;能够直接调用GPU加速模型训练和推理。这个镜像特别适合需要快速搭建深度学习…...