基于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协议栈 处理网络协议,支持多客户端连接高效数据收发

相关推荐
TechWayfarer2 小时前
知乎/微博的IP属地显示为什么偶尔错误?用IP归属地查询平台自检工具3步验证
网络·python·网络协议·tcp/ip·网络安全
Wave8452 小时前
从单片机开发看透网络底层:Wi-Fi、TCP/IP 与 HTTP 的通俗解析
网络·单片机·tcp/ip
郝亚军2 小时前
ubuntu通过samba,让win11可以访问其共享文件夹
linux·服务器·ubuntu
农村小镇哥3 小时前
nginx服务器的介绍
运维·服务器·nginx
小夏子_riotous3 小时前
Docker学习路径——3、常用命令
linux·运维·服务器·学习·docker·容器·centos
2401_873479404 小时前
应急响应:勒索软件攻击源IP分析,如何通过IP地址查询定位辅助溯源?
网络·tcp/ip·安全·网络安全·ip
jghhh015 小时前
基于STM32的桌面Mini时钟设计
stm32·单片机·嵌入式硬件
IMPYLH5 小时前
Linux 的 rm 命令
linux·运维·服务器·网络·bash
white-persist6 小时前
【vulhub shiro 漏洞复现】vulhub shiro CVE-2016-4437 Shiro反序列化漏洞复现详细分析解释
运维·服务器·网络·python·算法·安全·web安全
代码中介商7 小时前
手把手教你Linux 打包压缩与 gcc 编译详解
linux·运维·服务器·编译·打包·压缩