基于 GD32F450 与 ENC28J60 的 TCP 通信实现
一、系统架构
graph TD
A[GD32F450] -->|SPI| B(ENC28J60)
B -->|RJ45| C[以太网]
D[TCP客户端] -->|IP:192.168.1.100| B
A --> E[应用程序]
二、关键开发步骤
硬件接口配置
SPI 时钟配置:
引脚映射:
SCK: PA5
MISO: PA6
MOSI: PA7
CS: PA4
INT: PA3
ENC28J60 驱动层
// ENC28J60 初始化
void ENC28J60_Init(void) {
SPI_Config(); // SPI 初始化
ETH_Reset(); // 硬件复位
// 设置接收缓冲区
ENC28J60_WriteReg(ERXSTL, RX_BUF_START & 0xFF);
ENC28J60_WriteReg(ERXSTH, RX_BUF_START >> 8);
// 启用接收功能
ENC28J60_BitSet(ECON1, ECON1_RXEN);
}
TCP/IP 协议栈实现
ARP 协议处理
IP 分片重组
TCP 状态机:
TCP 连接建立代码
// TCP 三次握手处理
void TCP_Handshake(tcp_pcb* pcb) {
// 发送 SYN
tcp_send_syn(pcb);
// 等待 SYN-ACK
while(pcb->state != SYN_RCVD);
// 发送 ACK
tcp_send_ack(pcb);
}
三、数据传输实现
数据发送流程
void TCP_SendData(uint8_t* data, uint16_t len) {
// 创建TCP段
tcp_seg* seg = tcp_create_seg(pcb, data, len);
// 添加到发送队列
tcp_enqueue(pcb, seg);
// 触发发送
ENC28J60_StartTransmit();
}
数据接收处理
// 接收回调函数
err_t tcp_recv_cb(void* arg, tcp_pcb* pcb, pbuf* p, err_t err) {
if (p != NULL) {
// 处理接收数据
ProcessData(p->payload, p->len);
pbuf_free(p); // 释放缓冲区
}
return ERR_OK;
}
四、关键参数配置
五、调试要点
网络连通性测试
ping 192.168.1.50 # 测试基础连通性
telnet 192.168.1.50 8080 # 测试TCP端口
常见问题解决
丢包问题:检查 SPI 时序,确保时钟频率 ≤ 20MHz
连接超时:验证 ARP 缓存表是否正确建立
数据校验错误:启用 ENC28J60 的 CRC 校验功能
ENC28J60_BitSet(ECON1, ECON1_CRCEN);
六、性能优化
启用 DMA 传输:
2
实现 Nagle 算法减少小包传输
提示:完整实现需结合 lwIP 或 uIP 协议栈,上述代码为精简示例。实际开发中建议使用硬件定时器处理 TCP 超时重传,避免阻塞主循环。
————————————————
版权声明:本文为CSDN博主「2501_93939917」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/2501_93939917/article/details/154250653
|
|