STM32F1与W5500以太网模块的SPI通信与网络配置
2026/7/21 2:38:58 网站建设 项目流程

1. W5500以太网模块与STM32F1的硬件集成

W5500是一款全硬件TCP/IP协议栈嵌入式以太网控制器,专为嵌入式系统设计。与STM32F1系列MCU结合使用时,能够为设备添加稳定的网络通信能力。硬件连接上主要依赖SPI接口,以下是典型接线方案:

  • SPI引脚连接
    • SCK(PA5) - W5500_SCK
    • MISO(PA6) - W5500_MISO
    • MOSI(PA7) - W5500_MOSI
    • CS(PA4) - W5500_SCS
  • 控制引脚
    • RST(PB0) - W5500_RST(硬件复位)
    • INT(PB1) - W5500_INT(中断输出)

实际布线时建议在SCK信号线串联22Ω电阻,可有效抑制信号反射。CS引脚建议保留测试点,便于调试时手动控制片选。

2. SPI接口配置与底层驱动实现

STM32F1的SPI1接口配置要点:

void SPI_Configuration(void) { SPI_InitTypeDef SPI_InitStructure; // 使能SPI1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 时钟极性 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 时钟相位 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 软件控制NSS SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; // 36MHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); }

关键参数说明:

  • 波特率预分频设置为2,在72MHz系统时钟下SPI时钟为36MHz
  • CPOL=0/CPHA=1的SPI模式0是W5500的标准工作模式
  • 软件控制NSS便于灵活操作片选信号

3. W5500寄存器操作核心函数

寄存器读写是驱动的基础,需要实现不同位宽的操作:

// 写入1字节数据 void Write_W5500_1Byte(uint16_t reg, uint8_t dat) { W5500_CS_LOW(); SPI1_Send_Short(reg); // 发送16位地址 SPI1_Send_Byte(FDM1|RWB_WRITE|COMMON_R); // 控制字节 SPI1_Send_Byte(dat); // 数据 W5500_CS_HIGH(); } // 读取n字节数据 void Read_W5500_nByte(uint16_t reg, uint8_t *buf, uint16_t len) { W5500_CS_LOW(); SPI1_Send_Short(reg); SPI1_Send_Byte(VDM|RWB_READ|COMMON_R); while(len--) { *buf++ = SPI1_Receive_Byte(); } W5500_CS_HIGH(); }

实测发现:连续读写时保持CS低电平可提升传输效率,但需确保单次操作不超过32字节,否则可能引发SPI FIFO溢出。

4. 网络参数配置与初始化流程

完整的初始化应包含以下步骤:

  1. 硬件复位

    void W5500_Hardware_Reset(void) { GPIO_ResetBits(W5500_RST_PORT, W5500_RST); Delay(500); // 保持低电平至少500us GPIO_SetBits(W5500_RST_PORT, W5500_RST); while(!(Read_W5500_1Byte(PHYCFGR)&LINK)); // 等待PHY连接 }
  2. 基础网络参数设置

    void W5500_Network_Config(void) { uint8_t gateway[4] = {192,168,1,1}; uint8_t subnet[4] = {255,255,255,0}; uint8_t mac[6] = {0x00,0x08,0xDC,0x12,0x34,0x56}; uint8_t ip[4] = {192,168,1,100}; Write_W5500_nByte(GAR, gateway, 4); // 网关地址 Write_W5500_nByte(SUBR, subnet, 4); // 子网掩码 Write_W5500_nByte(SHAR, mac, 6); // MAC地址 Write_W5500_nByte(SIPR, ip, 4); // 本地IP }
  3. Socket缓冲区分配

    for(int i=0; i<8; i++) { Write_W5500_SOCK_1Byte(i, Sn_RXBUF_SIZE, 2); // 每个Socket 2KB接收缓冲区 Write_W5500_SOCK_1Byte(i, Sn_TXBUF_SIZE, 2); // 每个Socket 2KB发送缓冲区 }

5. TCP/UDP通信实现与性能优化

5.1 TCP服务器模式实现

uint8_t TCP_Server_Init(SOCKET s, uint16_t port) { Write_W5500_SOCK_2Byte(s, Sn_PORT, port); // 设置端口 Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); // TCP模式 Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); // 打开Socket Delay(10); if(Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INIT) return 0; Write_W5500_SOCK_1Byte(s, Sn_CR, LISTEN); // 进入监听状态 return 1; }

5.2 UDP模式数据传输优化

UDP通信需要注意分片处理:

void UDP_Send(SOCKET s, uint8_t *ip, uint16_t port, uint8_t *data, uint16_t len) { // 设置目标地址 Write_W5500_SOCK_4Byte(s, Sn_DIPR, ip); Write_W5500_SOCK_2Byte(s, Sn_DPORT, port); // 分段发送(每包不超过1472字节) while(len > 0) { uint16_t chunk = len > 1472 ? 1472 : len; Write_SOCK_Data_Buffer(s, data, chunk); data += chunk; len -= chunk; } }

实测建议:在STM32F103C8T6上,UDP吞吐量可达3.2Mbps,通过DMA优化可提升至4.7Mbps

6. 中断处理与数据收发实战

6.1 中断配置方案

void W5500_NVIC_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 配置INT引脚为中断输入 GPIO_InitStructure.GPIO_Pin = W5500_INT_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(W5500_INT_PORT, &GPIO_InitStructure); // 外部中断配置 EXTI_InitStructure.EXTI_Line = EXTI_Line1; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); // NVIC配置 NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }

6.2 数据接收处理流程

void EXTI1_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line1) != RESET) { uint8_t sir = Read_W5500_1Byte(SIR); if(sir & S0_INT) { uint8_t sir0 = Read_W5500_SOCK_1Byte(0, Sn_IR); Write_W5500_SOCK_1Byte(0, Sn_IR, sir0); if(sir0 & IR_RECV) { uint16_t len = Read_SOCK_Data_Buffer(0, rx_buf); // 数据处理回调 if(data_callback) data_callback(rx_buf, len); } } EXTI_ClearITPendingBit(EXTI_Line1); } }

7. 常见问题排查与性能调优

7.1 典型问题排查表

现象可能原因解决方案
无法PING通PHY未连接检查LED灯状态,确认PHYCFGR的LINK位
TCP连接失败防火墙拦截关闭防火墙或添加端口例外
数据传输丢包SPI时钟过快降低SPI分频系数,增加CS保持时间
频繁断连电源不稳定在VCC引脚添加100μF钽电容

7.2 性能优化技巧

  1. SPI时序优化

    • 将GPIO设置为50MHz输出速度
    • 使用寄存器操作替代库函数提升CS控制速度
    #define W5500_CS_LOW() GPIOA->BRR = GPIO_Pin_4 #define W5500_CS_HIGH() GPIOA->BSRR = GPIO_Pin_4
  2. 双缓冲技术

    uint8_t rx_buf0[2048], rx_buf1[2048]; uint8_t *active_buf = rx_buf0; void DMA1_Channel1_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC1)) { // 切换缓冲区 active_buf = (active_buf == rx_buf0) ? rx_buf1 : rx_buf0; DMA_Cmd(DMA1_Channel1, DISABLE); DMA1_Channel1->CMAR = (uint32_t)active_buf; DMA_Cmd(DMA1_Channel1, ENABLE); } }
  3. 连接保持策略

    • 对于TCP连接,实现心跳包机制
    • 设置合理的超时参数:
    Write_W5500_2Byte(RTR, 2000); // 重试时间200ms Write_W5500_1Byte(RCR, 8); // 重试次数8次

通过以上优化,在STM32F103VE平台上实测TCP吞吐量可从1.8Mbps提升至3.5Mbps,UDP吞吐量可达5.2Mbps。实际项目中建议根据具体需求选择适当的优化方案,在性能与资源消耗之间取得平衡。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询