基于STM32F107和DP83848的TCP服务器数据收发方案

一、系统概述

基于STM32F107VCT6 (带以太网MAC控制器)和DP83848C (10/100M以太网PHY芯片),通过RMII接口 实现TCP服务器功能,支持多客户端连接数据收发低功耗管理 。系统采用LWIP协议栈(轻量级TCP/IP)实现网络层功能,适用于工业控制、远程监测、物联网网关等场景。

二、硬件设计

1. 核心组件选型

组件 型号/规格 功能说明
主控芯片 STM32F107VCT6 带ETH MAC,256KB Flash,64KB RAM
PHY芯片 DP83848C 10/100M RMII PHY,支持自动协商
网络变压器 HR911105A RJ45集成变压器,隔离干扰
晶振 25MHz(ETH专用) 为DP83848提供时钟
电源 3.3V LDO(AMS1117) 为STM32和DP83848供电

2. 硬件连接(RMII接口)

DP83848引脚 STM32F107引脚 功能说明
TXD0 PA2 (ETH_RMII_TXD0) 发送数据0(RMII)
TXD1 PA3 (ETH_RMII_TXD1) 发送数据1(RMII)
TX_EN PA1 (ETH_RMII_TX_EN) 发送使能(RMII)
RXD0 PC4 (ETH_RMII_RXD0) 接收数据0(RMII)
RXD1 PC5 (ETH_RMII_RXD1) 接收数据1(RMII)
CRS_DV PA7 (ETH_RMII_CRS_DV) 载波侦听/数据有效(RMII)
RX_ER PG2 (ETH_RMII_RX_ER) 接收错误(可选)
REF_CLK PA8 (ETH_RMII_REF_CLK) RMII参考时钟(50MHz)
MDIO PA2 (ETH_MDIO) PHY管理数据接口
MDC PC1 (ETH_MDC) PHY管理时钟(最高2.5MHz)
RESET PB11 (GPIO) 复位(低电平有效)

三、软件设计(STM32CubeMX + LWIP)

1. STM32CubeMX配置

(1)时钟与ETH
  • 系统时钟:HSE=25MHz → PLL×9 → 72MHz SYSCLK(ETH时钟需25MHz,由外部晶振提供);

  • ETH配置

  • 接口:RMII;

  • PHY地址:0x01(DP83848默认地址);

  • 模式:全双工,100M(或自适应);

  • 使能DMA(接收/发送描述符)。

(2)LWIP协议栈配置
  • 启用LWIP:在"Middleware"中选择LWIP,配置:

  • IP地址:192.168.1.100(静态IP);

  • 子网掩码:255.255.255.0;

  • 网关:192.168.1.1;

  • TCP服务器端口:8080;

  • 内存配置:

    • MEM_SIZE=16KB(LWIP内存池);

    • TCP_MSS=1460(TCP最大段大小);

    • TCP_WND=8KB(TCP窗口大小)。

(3)生成工程

选择MDK-ARM或STM32CubeIDE,生成HAL库工程,自动包含ETH和LWIP驱动。

2. 核心代码实现

(1)ETH与LWIP初始化(自动生成,略作修改)
c 复制代码
// ethernetif.c(LWIP网络接口层)
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "stm32f1xx_hal.h"

// 网络接口结构体
struct netif gnetif;

// ETH初始化
void ETH_BSP_Config(void) {
  // 使能ETH时钟
  __HAL_RCC_ETH_CLK_ENABLE();
  // 配置RMII接口(CubeMX自动生成)
  // ...
}

// LWIP初始化
void LwIP_Init(void) {
  ip4_addr_t ipaddr, netmask, gw;
  IP4_ADDR(&ipaddr, 192, 168, 1, 100);
  IP4_ADDR(&netmask, 255, 255, 255, 0);
  IP4_ADDR(&gw, 192, 168, 1, 1);
  
  // 添加网络接口
  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
  netif_set_default(&gnetif);
  netif_set_up(&gnetif);
}
(2)TCP服务器实现(应用层)
c 复制代码
// tcp_server.c
#include "tcp_server.h"
#include "lwip/tcp.h"
#include "lwip/err.h"
#include <string.h>

// TCP控制块
static struct tcp_pcb *tcp_server_pcb;

// 接收回调函数
static err_t TCP_Server_Recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
  if (p == NULL) { // 客户端断开连接
    tcp_close(tpcb);
    return ERR_OK;
  }
  
  // 处理接收数据(示例:回显数据)
  char *data = (char*)p->payload;
  uint16_t len = p->len;
  tcp_write(tpcb, data, len, TCP_WRITE_FLAG_COPY); // 回显
  tcp_recved(tpcb, p->tot_len); // 通知LWIP已接收数据
  pbuf_free(p); // 释放pbuf
  return ERR_OK;
}

// 连接回调函数
static err_t TCP_Server_Accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
  tcp_recv(newpcb, TCP_Server_Recv); // 绑定接收回调
  return ERR_OK;
}

// 创建TCP服务器
void TCP_Server_Init(uint16_t port) {
  tcp_server_pcb = tcp_new(); // 创建TCP控制块
  if (tcp_bind(tcp_server_pcb, IP_ADDR_ANY, port) != ERR_OK) {
    // 绑定失败
    return;
  }
  tcp_listen(tcp_server_pcb); // 监听端口
  tcp_accept(tcp_server_pcb, TCP_Server_Accept); // 绑定连接回调
}
(3)主程序逻辑
c 复制代码
// main.c
#include "main.h"
#include "lwip.h"
#include "tcp_server.h"

int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_ETH_Init();
  MX_LWIP_Init(); // 初始化LWIP
  
  // 创建TCP服务器(端口8080)
  TCP_Server_Init(8080);
  
  while (1) {
    // 主循环:处理LWIP任务(CubeMX自动生成)
    MX_LWIP_Process();
  }
}

参考代码 基于STM32F107和DP83848芯片的TCP服务器收发数据 www.youwenfan.com/contentcss/101784.html

四、关键功能实现

1. 多客户端连接管理

  • 连接池 :使用链表管理多个客户端TCP控制块(struct tcp_pcb);

  • 并发处理:LWIP为单线程事件驱动,通过回调处理多客户端数据,避免阻塞。

c 复制代码
// 多客户端管理示例
typedef struct {
  struct tcp_pcb *pcb;
  uint8_t connected;
} Client_Info;

Client_Info clients[5]; // 最大5个客户端

// 在Accept回调中分配客户端
static err_t TCP_Server_Accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
  for (int i=0; i<5; i++) {
    if (!clients[i].connected) {
      clients[i].pcb = newpcb;
      clients[i].connected = 1;
      tcp_recv(newpcb, TCP_Server_Recv);
      return ERR_OK;
    }
  }
  tcp_close(newpcb); // 超过最大连接数,拒绝
  return ERR_MEM;
}

2. 数据收发优化

  • 零拷贝 :使用pbuf直接访问数据,减少内存复制;

  • 分片传输 :大数据分包发送(如tcp_write分多次调用);

  • 流量控制 :通过TCP_WND调整接收窗口,避免缓冲区溢出。

c 复制代码
// 大数据发送示例(分片)
void Send_LargeData(struct tcp_pcb *tpcb, uint8_t *data, uint32_t len) {
  uint32_t offset = 0;
  while (len > 0) {
    uint16_t send_len = (len > TCP_MSS) ? TCP_MSS : len;
    tcp_write(tpcb, data+offset, send_len, TCP_WRITE_FLAG_COPY);
    offset += send_len;
    len -= send_len;
  }
  tcp_output(tpcb); // 立即发送
}

3. 低功耗设计

  • ETH休眠:无数据时,STM32进入停止模式,通过ETH中断唤醒;

  • LWIP低功耗 :配置LWIP_DHCP动态获取IP,空闲时关闭广播。

c 复制代码
// 进入低功耗模式
void Enter_LowPowerMode(void) {
  // 关闭ETH时钟
  __HAL_RCC_ETH_CLK_DISABLE();
  // 进入停止模式
  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  // 唤醒后恢复
  SystemClock_Config();
  __HAL_RCC_ETH_CLK_ENABLE();
  ETH_BSP_Config();
}

五、测试与验证

1. 测试工具

  • 网络调试助手(如NetAssist):作为TCP客户端,连接STM32的IP(192.168.1.100:8080),发送数据并接收回显;

  • Wireshark:抓包分析TCP握手、数据传输过程;

  • 示波器:测量RMII接口信号(TXD/RXD)波形,验证通信速率。

2. 测试项目

测试项 测试方法 预期结果
服务器启动 上电后查看IP配置 正确获取IP(192.168.1.100)
客户端连接 用NetAssist连接8080端口 连接成功,显示"Connected"
数据收发 发送"Hello",接收回显 接收数据与发送一致
多客户端连接 同时连接3个客户端 均能正常收发数据
断线重连 拔掉网线后重连 自动恢复连接(DHCP场景)

六、注意事项

1. 硬件设计

  • RMII时钟:PA8(REF_CLK)需接25MHz时钟(由DP83848或外部晶振提供),确保与STM32的ETH模块同步;

  • 网络变压器:必须使用带中心抽头的变压器(如HR911105A),隔离PHY与RJ45,减少共模干扰;

  • 电源滤波:DP83848的VCC引脚并联10μF+0.1μF电容,减少电源纹波。

2. 软件配置

  • PHY地址:DP83848的PHY地址由ADDR引脚决定(默认0x01,若ADDR接高则为0x05),需在CubeMX中正确配置;

  • LWIP内存 :根据应用需求调整MEM_SIZETCP_WND,避免内存溢出(STM32F107的64KB RAM需合理分配);

  • 中断优先级:ETH中断优先级需高于LWIP任务,确保数据及时接收。

七、总结

本方案基于STM32F107和DP83848实现了TCP服务器功能,通过RMII接口 连接PHY芯片,LWIP协议栈 处理网络协议,支持多客户端连接高效数据收发

相关推荐
番茄去哪了2 小时前
Retrofit框架调用第三方api
java·服务器·retrofit
攻城狮在此2 小时前
MobaXterm下载安装及SSH远程连接(交换机/路由器/服务器)
linux·运维·服务器·网络
花间相见2 小时前
【Agent开发】—— ToolCall 、 FunctionCall 底层原理与极简实现
运维·服务器
mounter6252 小时前
【LSF/MM内核前沿】Linux 内存回收推倒重来?解析 MGLRU 与传统 LRU 的“统一之战”
linux·运维·服务器·网络·内核·内存回收
BackCatK Chen3 小时前
STM32保姆级入门教程|第5章:GPIO内部结构 + 8种模式 + 功能详解
stm32·嵌入式硬件·gpio·推挽输出·开漏输出·gpio内部结构·上拉输入
Exquisite.3 小时前
k8s的Pod管理
linux·运维·服务器
IMPYLH3 小时前
Linux 的 env 命令
linux·运维·服务器·数据库
桌面运维家3 小时前
Nginx服务器安全:高级访问控制与流量清洗实战
服务器·nginx·安全
FPGA小迷弟3 小时前
FPGA工程师面试题汇总(九)
网络协议·tcp/ip·fpga开发·面试·verilog·fpga