基于STM32F407与LAN8720A实现以太网通信
一、硬件连接方案(RMII模式)
graph LR
A[STM32F407] -->|RMII接口| B[LAN8720A]
A -->|GPIO| B
subgraph STM32F407
ETH_MDC --> GPIOC1
ETH_MDIO --> GPIOA2
ETH_RMII_REF_CLK --> GPIOA1
ETH_RMII_CRS_DV --> GPIOA7
ETH_RMII_RXD0 --> GPIOC4
ETH_RMII_RXD1 --> GPIOC5
ETH_RMII_TX_EN --> GPIOG11
ETH_RMII_TXD0 --> GPIOG13
ETH_RMII_TXD1 --> GPIOG14
ETH_RESET --> GPIOD3
end
subgraph LAN8720A
MDC --> ETH_MDC
MDIO --> ETH_MDIO
RX_CLK --> ETH_RMII_REF_CLK
RX_DV --> ETH_RMII_CRS_DV
RX_ER --> NC
RXD0 --> ETH_RMII_RXD0
RXD1 --> ETH_RMII_RXD1
TX_CLK --> ETH_RMII_TX_CLK
TX_EN --> ETH_RMII_TX_EN
TXD0 --> ETH_RMII_TXD0
TXD1 --> ETH_RMII_TXD1
nRST --> ETH_RESET
end
二、软件实现流程
2.1 CubeMX配置(关键参数)
-
时钟配置
- HSE设置为外部8MHz晶振
- PLL配置:PLL_SRC=HSE, PLLM=8, PLLN=336, PLLP=2, PLLQ=7
- ETH时钟源选择PLL2(需启用PLL2)
-
以太网配置
- 模式选择:RMII
- PHY地址:0x01(根据实际电路调整)
- 自动协商:启用
- 接收缓冲区:20个(ETH_RXBUFNB=20)
-
LWIP配置
#define LWIP_DHCP 1 #define LWIP_NETIF_HOSTNAME 1 #define MEM_SIZE (16 * 1024) #define PBUF_POOL_SIZE 16 #define TCPIP_THREAD_STACKSIZE 1024
2.2 PHY驱动代码(HAL库实现)
// PHY复位函数
void PHY_Reset(void) {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_Delay(50);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_SET);
HAL_Delay(100);
}
// PHY状态检测
uint8_t PHY_LinkStatus(void) {
uint16_t regval = ETH_ReadPHYRegister(0x01, 0x0001);
return (regval & 0x0004) ? 1 : 0; // Link status bit
}
// 初始化流程
void MX_ETH_Init(void) {
__HAL_RCC_ETH_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 配置RMII引脚(代码参考CubeMX生成)
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
PHY_Reset();
HAL_Delay(200);
// 配置自动协商
ETH_ConfigPhy(ETH_AUTONEGOTIATION_ENABLE);
}
2.3 LWIP协议栈集成
// 网络接口初始化
struct netif gnetif;
void lwip_init_system(void) {
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, eth_init, ethernet_input);
netif_set_default(&gnetif);
netif_set_up(&gnetif);
}
// 低层接口实现
err_t eth_init(struct netif *netif) {
netif->linkoutput = eth_linkoutput;
netif->output = eth_output;
netif->state = (void*)&mac_address;
return ERR_OK;
}
// 数据包发送
err_t eth_linkoutput(struct netif *netif, struct pbuf *p) {
return HAL_ETH_TransmitFrame(&heth, p->payload, p->len);
}
三、关键功能实现
3.1 TCP服务器
void tcp_server_task(void *arg) {
struct tcp_pcb *pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 8080);
tcp_listen(pcb);
while(1) {
struct tcp_pcb *newpcb = tcp_accept(pcb, tcp_accept_cb);
if(newpcb) {
tcp_arg(newpcb, newpcb);
tcp_recv(newpcb, tcp_recv_cb);
tcp_err(newpcb, tcp_err_cb);
}
}
}
// 接收回调
err_t tcp_recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
if(p) {
// 处理接收数据
tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY);
pbuf_free(p);
}
return ERR_OK;
}
3.2 UDP广播
void udp_broadcast_task(void) {
struct udp_pcb *upcb = udp_new();
udp_bind(upcb, IP_ADDR_ANY, 0);
while(1) {
uint8_t msg[] = "Hello World";
udp_sendto(upcb, msg, sizeof(msg), IP_ADDR_BROADCAST, 1234);
HAL_Delay(1000);
}
}
四、完整工程结构
STM32F407_ETH_Driver/
├── Core/
│ ├── Inc/
│ │ ├── main.h
│ │ ├── lwipopts.h
│ │ └── lan8720.h
│ └── Src/
│ ├── main.c
│ ├── lwip.c
│ └── lan8720.c
├── Drivers/
│ ├── CMSIS/
│ └── STM32F4xx_HAL_Driver/
└── Middlewares/
└── lwIP/
五、扩展功能实现
5.1 MQTT协议集成
#include "mqtt_client.h"
void mqtt_connect() {
mqtt_client_connect("broker.hivemq.com", 1883, "STM32_Client");
}
void mqtt_publish() {
mqtt_publish("topic/sensor", "Hello MQTT", strlen("Hello MQTT"));
}
5.2 Web服务器实现
void web_server_init() {
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.uri_match_fn = httpd_uri_match_wildcard;
httpd_uri_t uri_get = {
.uri = "/status",
.method = HTTP_GET,
.handler = status_handler,
.user_ctx = NULL
};
httpd_register_uri_handler(server, &uri_get);
}
参考代码 通过STM32F407来驱动LAN8720A实现网络通信 www.youwenfan.com/contentcnl/57058.html
六、测试验证
-
基础测试
ping 192.168.1.100 # 预期结果:Reply from 192.168.1.100: bytes=32 time<1ms TTL=64 -
流量测试
// 使用iperf3测试带宽 iperf3 -s # 服务端 iperf3 -c 192.168.1.100 # 客户端 -
压力测试
// 持续发送1000个TCP连接 for(i=0; i<1000; i++) { tcp_client_connect("192.168.1.100", 8080); }
浙公网安备 33010602011771号