全部例程

以太网测速示例

W6300

更新于 2026年10月14日

本篇总结

在 W6300 上借助 Jperf 图形化测速工具,通过建立无时延 TCP 客户端持续发送数据测量以太网带宽,实测可达 39.9Mbits/s。

🔑 MH2457 + QSPI、UART 调试、硬件 TOE 引擎、TCP、Jperf

硬件平台:本例程基于 W6300-EVB-M4 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板

本示例演示如何在 W6300 上实现以太网测速功能,并通过实战例程,为大家讲解如何通过 Jperf 工具进行测速。该例程用到的其他网络协议(例如 DHCP)以及 W6300 的初始化过程,请参考 Network Install 章节,这里不再赘述。

前置工具准备

开始本例程前,请确认以下工具已安装:

  • WIZ UartTool V1.0:串口调试工具:点击下载
  • Jperf(含 JRE):基于 Java 的图形化网络性能测速工具,是 Iperf 的 GUI 版本:点击下载

Jperf 测试工具简介

JPerf 是基于 Java 的图形化网络性能测试工具,是 Iperf 的图形用户界面(GUI)版本,通过图形化界面让用户无需命令行操作即可完成 TCP/UDP 协议的带宽、延迟和丢包测试,支持实时性能监控,可在 Windows、Linux、macOS 跨平台运行。

  • 图形化界面:直观的 GUI 简化 Iperf 配置与运行,轻松配置测试时长、数据量、包大小等参数
  • 多协议实时监控:支持 TCP/UDP 协议,实时显示带宽、丢包率、延迟等性能数据
  • 跨平台:基于 Java,可在 Windows、Linux、macOS 运行

测速流程

安装 JRE → 安装 Jperf → 打开 jperf.bat 图形界面 → 配置工作模式与单位量程 → 对端发起测速。影响速率的关键因素包括 Socket 缓存大小、单次传输数据长度、TCP 重传参数及以太网差分布线。

硬件连接与拓扑

请注意:

测试需要 PC 端和 W6300 处于同一网段。

  1. Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
  2. 网线连接开发板 RJ45 网口 到路由器 LAN 口
┌─────────────────────────────────┐
│ 路由器(DHCP Server) │
│ 192.168.1.1 │
└────┬──────────────────┬───────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ W6300 │ │ PC │
│ JPerf Clt │ │ JPerf GUI │
│ IP: DHCP │ │ IP: DHCP │
└────┬──────┘ └───────────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │─────────→ WIZ UartTool
│ MCU │
└───────────┘
网络拓扑:MH2457 通过 QSPI 驱动 W6300,开发板与 PC 在同一局域网内,通过路由器互通

工程结构

工程核心文件如下:

velocity_measurement/
├── main.c                    ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
└── USER/
    ├── user_main.c           ← 网络地址定义 + 测速数据填充 + 主循环
    ├── velocity_measurement.c/h ← do_velocity_measurement() 状态机 + Socket 缓存初始化
    ├── wiz_platform.c/h      ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
    └── wiz_interface.c/h     ← W6300 驱动接口:wizchip_initialize、network_init、PHY 检测

步骤1:填充测速数据

文件:USER/user_main.c — 循环填充 A-Z 字符作为测速发送数据。

/* 填充测速数据:循环填充 A-Z 字符 */
for (uint16_t i = 0; i < ETHERNET_BUF_MAX_SIZE; i++)
{
    ethernet_buf[i] = 65 + i % 26;
}

测速前先将发送缓冲区 ethernet_buf 填充为 A-Z 循环字符,作为持续发送的测速数据。

步骤2:初始化 Socket 缓存

文件:USER/velocity_measurement.c — 为测速 Socket 分配收发缓存,最大化单次吞吐量。

#define VELOCITY_SOCKET_BUFFER_KB 32U

int velocity_measurement_buffer_init(uint8_t sn)
{
    uint8_t i;

    if (sn >= _WIZCHIP_SOCK_NUM_)
    {
        return -1;
    }

    for (i = 0U; i < _WIZCHIP_SOCK_NUM_; i++)
    {
        setSn_TXBUF_SIZE(i, 0U);
        setSn_RXBUF_SIZE(i, 0U);
    }

    setSn_TXBUF_SIZE(sn, VELOCITY_SOCKET_BUFFER_KB);
    setSn_RXBUF_SIZE(sn, VELOCITY_SOCKET_BUFFER_KB);

    if ((getSn_TXBUF_SIZE(sn) != VELOCITY_SOCKET_BUFFER_KB) ||
        (getSn_RXBUF_SIZE(sn) != VELOCITY_SOCKET_BUFFER_KB))
    {
        return -1;
    }

    return 0;
}

先将所有 Socket 的收发缓存清零,再为测速 Socket 分配 VELOCITY_SOCKET_BUFFER_KB(32KB)收发缓存。W6300 片上 SRAM 共 64KB(32KB TX / 32KB RX),单 Socket 最大可分配 32KB。

如果你想自定义

  • 减小缓存对比速率差异 → 将 VELOCITY_SOCKET_BUFFER_KB 改为 16 或 8,观察测速结果变化
  • 总缓存不超过 64KB → 所有 Socket 的 TX 缓存之和 ≤ 32KB,RX 缓存之和 ≤ 32KB

步骤3:主循环调用 do_velocity_measurement() 进行测速

文件:USER/velocity_measurement.c — do_velocity_measurement() 函数创建无时延模式的 TCP 客户端,连接成功后持续发送数据。

#define VELOCITY_LOCAL_PORT_START 50000U
#define VELOCITY_LOCAL_PORT_END   60000U
#define VELOCITY_TCP_RTR          2000U
#define VELOCITY_TCP_RCR          20U

void do_velocity_measurement(uint8_t sn,
                             uint8_t *buffer_txst,
                             uint16_t buffer_len,
                             uint8_t *des_ip,
                             uint16_t des_port)
{
    static uint16_t local_port = VELOCITY_LOCAL_PORT_START;
    int32_t ret;
    uint8_t sr;

    sr = getSn_SR(sn);

    switch (sr)
    {
    case SOCK_INIT:
        setSn_RTR(sn, VELOCITY_TCP_RTR);
        setSn_RCR(sn, VELOCITY_TCP_RCR);

        ret = connect(sn, des_ip, des_port);
        if ((ret != SOCK_OK) && (ret != SOCK_BUSY))
        {
            if (getSn_SR(sn) != SOCK_CLOSED)
            {
                (void)close(sn);
            }
        }
        break;

    case SOCK_ESTABLISHED:
        if ((getSn_IR(sn) & Sn_IR_CON) != 0U)
        {
            setSn_IR(sn, Sn_IR_CON);
        }

        velocity_prepare_iperf2_payload(buffer_txst, buffer_len);
        ret = send(sn, buffer_txst, buffer_len);

        if ((ret < 0) && (ret != SOCK_BUSY))
        {
            if (getSn_SR(sn) != SOCK_CLOSED)
            {
                (void)close(sn);
            }
        }
        break;

    case SOCK_CLOSE_WAIT:
        (void)disconnect(sn);
        break;

    case SOCK_CLOSED:
        setSn_IR(sn, 0xFFU);

        ret = socket(sn, Sn_MR_TCP, local_port, Sn_MR_ND);
        if (ret == (int32_t)sn)
        {
            setSn_RTR(sn, VELOCITY_TCP_RTR);
            setSn_RCR(sn, VELOCITY_TCP_RCR);

            local_port++;
            if (local_port > VELOCITY_LOCAL_PORT_END)
            {
                local_port = VELOCITY_LOCAL_PORT_START;
            }
        }
        break;

    default:
        break;
    }
}

代码解析

该函数通过 getSn_SR(sn) 读取 Socket 状态机:SOCK_CLOSED 时以无时延模式(Sn_MR_ND)打开 TCP Socket;SOCK_INIT 时设置 TCP 重传参数并发起连接;SOCK_ESTABLISHED 时不断发送数据;SOCK_CLOSE_WAIT 时断开连接。

JPerf/iperf2 会检查 TCP 载荷的第一个 32 位字作为客户端标志,正常单向吞吐流以 flags = 0 开头,所以发送前先把缓冲区前 4 字节清零。

static void velocity_prepare_iperf2_payload(uint8_t *buffer, uint16_t len)
{
    if ((buffer != NULL) && (len >= IPERF2_FLAGS_SIZE))
    {
        buffer[0] = 0U;
        buffer[1] = 0U;
        buffer[2] = 0U;
        buffer[3] = 0U;
    }
}

运行验证

烧录例程运行后,首先进行 PHY 链路检测,然后打印网络地址信息,最后在未连接服务器时不断打印提示信息,直到连接上所设置的服务器为止。打开 WIZ UartTool V1.0,连接 DEBUG USB 对应 COM 口(115200 / 8N1),典型输出如下:

MH2457 W6300 QSPI example start
W6300 velocity_measurement example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
====================================================================================================
 W6300 network configuration : static

 MAC         : 00:08:DC:12:34:56
 IP          : 192.168.2.50
 Subnet Mask : 255.255.255.0
 Gateway     : 192.168.1.1
 DNS         : 0.0.0.0
====================================================================================================

打开 Jperf(jperf.bat),在 PC 端配置为 Server 模式监听端口,W6300 作为 Client 连接后持续发送数据。下面观察 Jperf 的测速结果。

JPerf 2.0 测速结果 — W6300 32KB Socket 缓存:39.9 Mbps

 

常见问题

Q: 为什么必须安装 JRE 才能使用 Jperf

JPerf 是基于 Java 开发的图形化应用程序,运行依赖于 Java 运行时环境(JRE)。没有 JRE 将无法启动 jperf.bat 图形界面,因此使用前必须先安装 JRE。

Q: 如何提升 W6300 的测速速率

可从四个方面优化:①增大 Socket 收发缓存(W6300 单 Socket 最大 32KB);②增大单次传输数据长度(如设为 2048 Byte);③合理设置 TCP 重传参数 RTR/RCR,避免重传过于激进;④保证以太网差分线布线规范,减少信号干扰。

Q: 测速时 PC 端和 W6300 不在同一网段怎么办

测试实例需要 PC 端和 W6300 处于同一网段才能正常通信。可通过修改 W6300 的网络地址信息(IP、子网掩码、网关)使其与 PC 端处于同一网段,或将 PC 端网卡 IP 设置到与 W6300 相同的网段。

Q: do_velocity_measurement 函数中无时延模式(Sn_MR_ND)有什么作用

无时延模式(Sn_MR_ND,No Delayed ACK)禁用了 TCP 的延迟确认机制,避免因等待 ACK 而造成的传输延迟,从而提升测速时的实际吞吐量。该模式下数据发送更加连续,适合带宽测试场景。

Q: 为什么发送前要把缓冲区前 4 字节清零

JPerf/iperf2 会检查 TCP 载荷的第一个 32 位字作为客户端标志。正常单向 TCP 吞吐流以 flags = 0 开头,如果不清零,iperf2 可能把测速数据误判为控制标志,导致测速异常。velocity_prepare_iperf2_payload() 函数负责在发送前将前 4 字节清零。

总结

  • 测速工具:借助 Jperf 图形化工具,基于 TCP 协议测量 W6300 以太网带宽
  • 实现步骤:填充测速数据 → 初始化 Socket 缓存(32KB)→ 主循环调用 do_velocity_measurement() 创建无时延 TCP 客户端持续发送数据
  • 关键因素:Socket 缓存大小、单次传输数据长度、TCP 重传参数 RTR/RCR、以太网差分线布线
  • 实测速率:32KB Socket 缓存 + 2048B 单次数据可达 39.9Mbits/s
  • 优化建议:W6300 单 Socket 缓存最大 32KB,合理配置 RTR/RCR 可显著提升吞吐量

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5

Andy

W5500 技术支持专家