RT-Thread系列10——ETH网口设备

文章目录

  • 1. ETH测试
    • 第一步:cubemx配置。
    • 第二步:board.h配置。
    • 第三步:rtthread settings配置
    • 第四步:以太网复位引脚设置
    • 第五步:修改rtthread源码
    • 第六步:修改 cubemx 生成的 main 函数
    • 第七步:编译运行。
    • 第七步:通信测试
  • 2. UDP/TCP通信测试
    • 2.1 UDP测试
      • 2.1.1 UPD 服务端测试
      • 2.1.2 UPD 客户端测试
    • 2.2 TCP通信测试
      • 2.1.2 TCP 客户端测试
      • 2.2.2 TCP 服务端测试

====>>> 文章汇总(有代码汇总) <<<====

目标:使用网口和电脑通信。

  • RT-Thread studio,版本: 2.2.6,不一样其实区别也不大
  • RT-Thread:标准版,4.0.3版本
  • 芯片包版本:0.1.9
  • 开发板:自己做的,主控STM32F407VET6。
  • 网口芯片:太网口LAN8720A
  • cubemx版本:6.8.1

cubemx版本不一样的话,网口的配置过程也不大一样。我现在用的麻烦一点。老版本的cubemx相对简单。

Finsh组件是创建工程后就默认开启的,无需任何配置。

1. ETH测试

新建工程,选择自己的芯片和调试接口即可。

第一步:cubemx配置。

首先配置时钟,一般都拉满。
在这里插入图片描述
勾选上调试的串口、网口。参数默认。

在这里插入图片描述

我这里调试用的串口2,一般都是串口1,根据自己的选择即可。
网口也要根据自己的板子的引脚调整。

生成代码后,关闭cubemx,直接编译,一堆报错,基本都在cubemx下面的main函数里面。

第二步:board.h配置。

在这里插入图片描述

第三步:rtthread settings配置

勾选以太网驱动。
在这里插入图片描述
勾选网络层驱动。
在这里插入图片描述
设置板子 IP 信息
在这里插入图片描述

勾选之后,保存 关闭。

第四步:以太网复位引脚设置

在这里插入图片描述

这里根据自己的板卡引脚修改。

第五步:修改rtthread源码

修改 eth_demo\rt-thread\components\drivers\include\drivers\phy.h文件,注释掉32行。图中 drivers 文件夹下的 drv_eth.c 报错是因为这个变量重定义了。
在这里插入图片描述

第六步:修改 cubemx 生成的 main 函数

在这里插入图片描述

注意,把下面的函数体 也删掉。

此时编译,应该是没有报错能通过的。cubemx中的main函数会用到我们删掉的那两个函数,所有会有警告,不想看可以在main函数中也注释或者删掉。

第七步:编译运行。

调试串口输入 ifconfig 就可以看到板子的ip信息了。
在这里插入图片描述

第七步:通信测试

第一步:把板子的网口和电脑的网口使用网线连接起来。

第二步:把电脑端 ip 更改为和板卡在同一个网段下。

更改本地电脑ip方法,自己百度一下。

在这里插入图片描述

第三步:打开电脑端 cmd 窗口,使用ping命令测试,可以ping通。
在这里插入图片描述
第四步:在串口调试助手中使用 ping命令测试,也可以ping通电脑。

如果不通,关掉电脑防火墙即可。

2. UDP/TCP通信测试

在上面的步骤都能通过以后,进行UDP/TCP通信测试。

2.1 UDP测试

在工程中新建一个 c 文件,添加如下代码。位置根据自己需要放。

/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2023-10-24     Haozi       the first version*/
#include <rtthread.h>
#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
#include <netdb.h>
#include <string.h>
#include <finsh.h>/* UDP服务器参数 */
#define BUFSZ                   1024        //接收缓存大小
#define BOARD_SERVER_PORT       5000        //板卡作为服务器的端口号/* UDP客户端参数 */
#define BOARD_UDP_CLIENT_PORT     20000               //板卡作为客户端端口号
#define UPPER_UDP_SERVER_IP       "192.168.1.125"     //要连接的服务器ip/** udp 服务端线程,一直等待接收其他udp客户端发来的消息。* 本机ip:192.168.1.30* 使用的端口号:5000
*/
void udp_server(void *para)
{int sock;int bytes_read;char *recv_data;socklen_t addr_len;struct sockaddr_in server_addr, client_addr;/* 分配接收用的数据缓冲 */recv_data = rt_malloc(BUFSZ);if (recv_data == RT_NULL){/* 分配内存失败,返回 */rt_kprintf("No memory\n");return;}/* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1){rt_kprintf("Socket error\n");/* 释放接收用的数据缓冲 */rt_free(recv_data);return;}/* 初始化服务端地址 */server_addr.sin_family = AF_INET;server_addr.sin_port = htons(BOARD_SERVER_PORT);server_addr.sin_addr.s_addr = INADDR_ANY;rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));/* 绑定socket到服务端地址 */if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){/* 绑定地址失败 */rt_kprintf("Bind error\n");/* 释放接收用的数据缓冲 */rt_free(recv_data);return;}addr_len = sizeof(struct sockaddr);rt_kprintf("UDPServer Waiting for client on port 5000...\n");while (1){/* 从sock中收取最大BUFSZ - 1字节数据 */bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0, (struct sockaddr *)&client_addr, &addr_len);/* UDP不同于TCP,它基本不会出现收取的数据失败的情况,除非设置了超时等待 */recv_data[bytes_read] = '\0'; /* 把末端清零 *//* 输出接收的数据 */rt_kprintf("\n(%s , %d) said : ", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));rt_kprintf("%s", recv_data);/* 如果接收数据是exit,退出 */if (strcmp(recv_data, "exit") == 0){closesocket(sock);/* 释放接收用的数据缓冲 */rt_free(recv_data);break;}}return;
}
MSH_CMD_EXPORT(udp_server, udp server);/** udp 客户端,每隔2s就往上位机发送当前系统时钟的计数值。* 本机ip:192.168.1.30* 使用的端口号:20000
*/
static const char send_data[] = "This is UDP Client from RT-Thread.\n"; /* 发送用到的数据 */void udp_client(void *para)
{int sock;struct hostent *host;struct sockaddr_in server_addr;/* 获得host地址(如果是域名,会做域名解析) */host = (struct hostent *) gethostbyname(UPPER_UDP_SERVER_IP);/* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1){rt_kprintf("Socket error\n");return;}/* 初始化预连接的服务端地址 */server_addr.sin_family = AF_INET;server_addr.sin_port = htons(BOARD_UDP_CLIENT_PORT);server_addr.sin_addr = *((struct in_addr *)host->h_addr);rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));/* 总计发送count次数据 */while (1){/* 发送数据到服务远端 */sendto(sock, send_data, strlen(send_data), 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));/* 线程休眠一段时间 */rt_thread_delay(2000);}/* 关闭这个socket */closesocket(sock);
}MSH_CMD_EXPORT(udp_client, udp client);

2.1.1 UPD 服务端测试

  1. 在串口调试助手中启动udp_server任务。
  2. 打开,网络调试助手。ip设置如下,然后点击连接。
  3. 在网络调试助手输入框输入消息并点击发送,串口会打印出板卡收到的消息。

在这里插入图片描述

电脑信息:端口是任意的,能连接即可。
板卡信息:端口是固定的,在上面板卡程序里面可以改。

2.1.2 UPD 客户端测试

  1. 打开,网络调试助手。ip设置如下。
  2. 重启板卡,在串口调试助手中启动 udp_client任务。
  3. 网络调试助手会受到板卡每2s发送过来的一次数据。

在这里插入图片描述

电脑信息:端口是固定的,在上面板卡程序里面可以改。
板卡信息:随便填吧,没用其实。

2.2 TCP通信测试

在工程中新建一个 c 文件,添加如下代码。位置根据自己需要放。

/** Copyright (c) 2006-2021, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2023-10-24     Haozi       the first version*/
#include <rtthread.h>
#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
#include <netdb.h>
#include <string.h>
#include <finsh.h>
#include <sys/errno.h>#define BUFSZ       (1024)
static const char send_data[] = "This is TCP Server from RT-Thread."; /* 发送用到的数据 *//*
* 程序清单:tcp 服务端** 这是一个 tcp 服务端的例程* 导出 tcpserv 命令到控制终端* 命令调用格式:tcpserv* 无参数* 程序功能:作为一个服务端,接收并显示客户端发来的数据 ,接收到 exit 退出程序
*/
void tcp_server(int argc, char **argv)
{char *recv_data; /* 用于接收的指针,后面会做一次动态分配以请求可用内存 */socklen_t sin_size;int sock, connected, bytes_received;struct sockaddr_in server_addr, client_addr;rt_bool_t stop = RT_FALSE; /* 停止标志 */int ret;recv_data = rt_malloc(BUFSZ + 1); /* 分配接收用的数据缓冲 */if (recv_data == RT_NULL){rt_kprintf("No memory\n");return;}/* 一个socket在使用前,需要预先创建出来,指定SOCK_STREAM为TCP的socket */if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){/* 创建失败的错误处理 */rt_kprintf("Socket error\n");/* 释放已分配的接收缓冲 */rt_free(recv_data);return;}/* 初始化服务端地址 */server_addr.sin_family = AF_INET;server_addr.sin_port = htons(20000); /* 服务端工作的端口 */server_addr.sin_addr.s_addr = INADDR_ANY;rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));/* 绑定socket到服务端地址 */if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){/* 绑定失败 */rt_kprintf("Unable to bind\n");/* 释放已分配的接收缓冲 */rt_free(recv_data);return;}/* 在socket上进行监听 */if (listen(sock, 5) == -1){rt_kprintf("Listen error\n");/* release recv buffer */rt_free(recv_data);return;}rt_kprintf("\nTCPServer Waiting for client on port 5000...\n");while (stop != RT_TRUE){sin_size = sizeof(struct sockaddr_in);/* 接受一个客户端连接socket的请求,这个函数调用是阻塞式的 */connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);/* 返回的是连接成功的socket */if (connected < 0){rt_kprintf("accept connection failed! errno = %d\n", errno);continue;}/* 接受返回的client_addr指向了客户端的地址信息 */rt_kprintf("I got a connection from (%s , %d)\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));/* 客户端连接的处理 */while (1){/* 发送数据到connected socket */ret = send(connected, send_data, strlen(send_data), 0);if (ret < 0){/* 发送失败,关闭这个连接 */closesocket(connected);rt_kprintf("\nsend error,close the socket.\r\n");break;}else if (ret == 0){/* 打印send函数返回值为0的警告信息 */rt_kprintf("\n Send warning,send function return 0.\r\n");}/* 从connected socket中接收数据,接收buffer是1024大小,但并不一定能够收到1024大小的数据 */bytes_received = recv(connected, recv_data, BUFSZ, 0);if (bytes_received < 0){/* 接收失败,关闭这个connected socket */closesocket(connected);break;}else if (bytes_received == 0){/* 打印recv函数返回值为0的警告信息 */rt_kprintf("\nReceived warning,recv function return 0.\r\n");closesocket(connected);break;}/* 有接收到数据,把末端清零 */recv_data[bytes_received] = '\0';if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0){/* 如果是首字母是q或Q,关闭这个连接 */closesocket(connected);break;}else if (strcmp(recv_data, "exit") == 0){/* 如果接收的是exit,则关闭整个服务端 */closesocket(connected);stop = RT_TRUE;break;}else{/* 在控制终端显示收到的数据 */rt_kprintf("RECEIVED DATA = %s \n", recv_data);}}}/* 退出服务 */closesocket(sock);/* 释放接收缓冲 */rt_free(recv_data);return ;
}
MSH_CMD_EXPORT(tcp_server, tcp server);/** 程序清单:tcp 客户端** 这是一个 tcp 客户端的例程* 导出 tcp_client 命令到控制终端* 命令调用格式:tcp_client URL PORT* URL:服务器地址 PORT::端口号* 程序功能:接收并显示从服务端发送过来的信息,接收到开头是 'q' 或 'Q' 的信息退出程序
*/
void tcp_client(int argc, char **argv)
{int ret;char *recv_data;struct hostent *host;int sock, bytes_received;struct sockaddr_in server_addr;const char *url;int port;if (argc < 3){rt_kprintf("Usage: tcp_client URL PORT\n");rt_kprintf("Like: tcp_client 192.168.1.125 20000\n");return ;}url = argv[1];port = strtoul(argv[2], 0, 10);/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */host = gethostbyname(url);/* 分配用于存放接收数据的缓冲 */recv_data = rt_malloc(BUFSZ);if (recv_data == RT_NULL){rt_kprintf("No memory\n");return;}/* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){/* 创建socket失败 */rt_kprintf("Socket error\n");/* 释放接收缓冲 */rt_free(recv_data);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), 0, sizeof(server_addr.sin_zero));/* 连接到服务端 */if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){/* 连接失败 */rt_kprintf("Connect fail!\n");closesocket(sock);/*释放接收缓冲 */rt_free(recv_data);return;}else{/* 连接成功 */rt_kprintf("Connect successful\n");}while (1){/* 从sock连接中接收最大BUFSZ - 1字节数据 */bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);if (bytes_received < 0){/* 接收失败,关闭这个连接 */closesocket(sock);rt_kprintf("\nreceived error,close the socket.\r\n");/* 释放接收缓冲 */rt_free(recv_data);break;}else if (bytes_received == 0){/* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */closesocket(sock);rt_kprintf("\nreceived error,close the socket.\r\n");/* 释放接收缓冲 */rt_free(recv_data);break;}/* 有接收到数据,把末端清零 */recv_data[bytes_received] = '\0';if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0){/* 如果是首字母是q或Q,关闭这个连接 */closesocket(sock);rt_kprintf("\n got a 'q' or 'Q',close the socket.\r\n");/* 释放接收缓冲 */rt_free(recv_data);break;}else{/* 在控制终端显示收到的数据 */rt_kprintf("\nReceived data = %s ", recv_data);}/* 发送数据到sock连接 */ret = send(sock, send_data, strlen(send_data), 0);if (ret < 0){/* 接收失败,关闭这个连接 */closesocket(sock);rt_kprintf("\nsend error,close the socket.\r\n");rt_free(recv_data);break;}else if (ret == 0){/* 打印send函数返回值为0的警告信息 */rt_kprintf("\n Send warning,send function return 0.\r\n");}}return;
}
MSH_CMD_EXPORT(tcp_client, tcp client);

2.1.2 TCP 客户端测试

  1. 网络调试助手设置为 TCP Server模式。并设置地址和端口号。
  2. 在串口调试助手中打开 TCP Client任务。接收电脑服务器发过去的数据。
  3. 在网络调试助手中输入要发送的消息点击发送,串口即可显示接收到的数据。

在这里插入图片描述

2.2.2 TCP 服务端测试

有问题,网络助手连接不上,后续再补。
百度说,把虚拟机的网络禁用就好了,这里测试没行,理由未知。

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

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

相关文章

C++阶段复习‘‘‘‘总结?【4w字。。。】

文章目录 前言类和对象C类定义和对象定义类成员函数C 类访问修饰符公有&#xff08;public&#xff09;成员私有&#xff08;private&#xff09;成员受保护&#xff08;protected&#xff09;成员 继承中的特点类的构造函数和析构函数 友元函数内联函数this指针指向类的指针类…

缩点+图论路径网络流:1114T4

http://cplusoj.com/d/senior/p/SS231114D 重新梳理一下题目 我们先建图 x → y x\to y x→y&#xff0c;然后对点分类&#xff1a;原串出现点&#xff0c;原串未出现点。 假如我们对一个原串出现点进行了操作&#xff0c;那么它剩余所有出边我们立刻去操作必然没有影响。所…

快速入门安装及使用git与svn的区别常用命令

一、导言 1、什么是svn&#xff1f; SVN是Subversion的简称&#xff0c;是一个集中式版本控制系统。与Git不同&#xff0c;SVN没有分布式的特性。在SVN中&#xff0c;项目的代码仓库位于服务器上&#xff0c;团队成员通过向服务器提交和获取代码来实现版本控制。SVN记录了每个…

专题知识点-二叉树-(非常有意义的一篇文章)

这里写目录标题 二叉树的基础知识知识点一(二叉树性质 )树与二叉树的相互转换二叉树的遍历层次优先遍历树的深度和广度优先遍历中序线索二叉树二叉树相关遍历代码顺序存储和链式存储二叉树的遍历二叉树的相关例题左右两边表达式求值求树的深度找数找第k个数二叉树非递归遍历代码…

蒙特卡洛树搜索(Monte Carlo Tree Search)揭秘

一. 什么是蒙特卡洛树搜索 蒙特卡洛树搜索(MCTS)是一种启发式搜索算法&#xff0c;一般用在棋牌游戏中&#xff0c;如围棋、西洋棋、象棋、黑白棋、德州扑克等。MCTS与人工神经网络结合&#xff0c;可发挥巨大的作用&#xff0c;典型的例子是2016年的AlphaGo&#xff0c;以4:1…

Elasticsearch:ES|QL 快速入门

警告&#xff1a;此功能处于技术预览阶段&#xff0c;可能会在未来版本中更改或删除。 Elastic 将努力解决任何问题&#xff0c;但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。目前的最新发行版为 Elastic Stack 8.11。 Elasticsearch 查询语言 (ES|QL) 提供了一种强…

快速构建高质量中文APP登录注册页面Figma源文件

在这个数字化时代&#xff0c;移动应用程序&#xff08;APP&#xff09;已经成为我们日常生活中不可或缺的一部分。如果您正在为您的中文APP开发登录注册页面&#xff0c;并寻找高质量的UI设计素材&#xff0c;那么您来对地方了&#xff01;我们为您提供了一个完整的Figma源文件…

Seatunnel单机和集群部署说明

编译 编译命令 mvn clean package -pl seatunnel-dist -am -Dmaven.test.skiptrue 部署 将seatunnel-dist\target目录下的apache-seatunnel-2.3.3-SNAPSHOT-bin.tar.gz上传至服务器 解压安装包到/opt/soft/seatunnel目录下 配置环境变量 export SEATUNNEL_HOME/opt/soft/s…

nginx之使用与配置教程

目录 简介 优点 安装 目录结构 nginx.conf配置文件结构 server虚拟主机配置 listen server_name location root index try_files proxy_pass 使用 反向代理 配置语法 常用指令 proxy_pass proxy_set_header proxy_redirect 负载均衡 负载均衡策略 轮询&…

竞赛选题 深度学习的动物识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

Java入门篇 之 继承

本篇碎碎念&#xff1a;最近的课程遇到瓶颈了&#xff0c;看的时候感觉自己会了&#xff0c;但是结束仔细一回顾还是一知半解&#xff0c;一点一点来吧&#xff0c;基础必须要打好(自己给自己好的心里暗示&#xff0c;结局一定是好的) 今日份励志文案:慢慢改变&#xff0c;慢慢…

SELF-AUGMENTED MULTI-MODAL FEATURE EMBEDDING

two embeddings f o r g _{org} org​ and f a u g _{aug} aug​ are combined using a gating mechanism 作者未提供代码

实战Leetcode(五)

Practice makes perfect&#xff01; 实战一&#xff1a; 思路&#xff1a;我们要用复制的节点来组成一个新的链表&#xff0c;而原链表的节点随机指向其中一个节点&#xff0c;我们首先给每一个节点都复制并且插入到原来节点的后面&#xff0c;然后用复制的节点指向我们原来节…

金财数科无代码开发平台:轻松实现电商、CRM、广告推广系统的集成连接

连接与集成&#xff1a;挖掘电商平台的潜力 金财数科是一家领先的信息技术公司&#xff0c;专注于利用前沿技术如互联网、人工智能、大数据和区块链等&#xff0c;为传统财税信息化方案和产品提供升级改造&#xff0c;并打造新一代智能财税SaaS平台。我们的目标是帮助企业通过…

电脑篇——本地串口转TCP,TCP转虚拟串口,网络调试助手,串口调试助手

TCP/UDP工具、串口工具 https://pan.baidu.com/s/1SY03d_RRVhyOZfsPlApmxg?pwd5555 今日有个需求&#xff0c;就是在本机电脑上接了一个串口设备&#xff0c;然后我的QtCreator是在内网远程电脑运行的&#xff0c;我想将串口设备“挂载”到远程电脑上去调试程序&#xff0c;于…

百望云携手华为发布金融信创与数电乐企联合方案 创新金融合规变革

10月27日&#xff0c;北京发布《关于开展全面数字化的电子发票试点工作的公告》&#xff0c;自2023年11月01日起开展数电票试点。千呼万唤始出来&#xff0c;拉开了北京地区企业开展数电票试点的序幕。 百望云作为数电票行业翘楚&#xff0c;电子发票服务平台供应商&#xff0c…

FiRa标准——MAC实现(二)

在IEEE 802.15.4z标准中&#xff0c;最关键的就是引入了STS&#xff08;加扰时间戳序列&#xff09;&#xff0c;实现了安全测距&#xff0c;大大提高了测距应用的安全性能。在FiRa的实现中&#xff0c;其密钥派生功能是非常重要的一个部分&#xff0c;本文首先对FiRa MAC中加密…

Spring面试题:(七)Spring AOP思想及实现

AOP思想的概念 AOP的实现&#xff1a;动态代理技术 通过spring容器获取目标对象和增强对象&#xff0c;通过动态代理生产代理对象&#xff0c;在目标对象的目标方法执行增强方法&#xff0c;返回生成代理对象给spring容器&#xff0c;在获取bean时则获取代理对象。 JDK代理和…

postman设置动态token, 每次登录更新token

postman设置动态token, 每次登录更新token 文章目录 postman设置动态token, 每次登录更新token问题1. 设置全局变量2. 新建登录接口3. 设置脚本4. 切换环境5. 配置动态token 问题 token过期时间一般比较短, 每次使用postman调用接口都token非常麻烦 实现token过期后, 调用一次…