一、系统概述
DM9051 是一款单芯片10/100M以太网控制器,集成MAC和PHY,支持SPI/并口接口,适合嵌入式系统。本设计基于STM32F103C8T6(Cortex-M3,72MHz,64KB Flash,20KB RAM)与DM9051通过SPI接口实现以太网通信,支持TCP/IP协议栈(LwIP),实现网络数据收发、远程监控、数据上传等功能,适用于工业物联网、智能家居网关、远程数据采集等场景。
二、硬件设计
1. 系统架构
SPI
MII/RMII
RJ45
I2C/SPI
GPIO
STM32F103C8T6
DM9051以太网控制器
网络变压器 HR911105A
以太网
传感器/外设
LED/按键
3.3V电源
2. 关键硬件连接
(1)核心芯片连接
| DM9051引脚 | 功能 | STM32F103C8T6引脚 | 说明 |
|---|---|---|---|
| VCC | 电源(3.3V) | 3.3V | 需加100nF去耦电容 |
| GND | 地 | GND | 共地 |
| SPI_CS | SPI片选 | PA4 (SPI1_NSS) | 低有效 |
| SPI_SCK | SPI时钟 | PA5 (SPI1_SCK) | 模式0(CPOL=0, CPHA=0) |
| SPI_MOSI | SPI主发从收 | PA7 (SPI1_MOSI) | 数据线 |
| SPI_MISO | SPI主收从发 | PA6 (SPI1_MISO) | 数据线 |
| INT | 中断输出 | PB0 (EXTI0) | 下降沿触发,通知数据到达 |
| RST | 复位 | PB1 (GPIO) | 低有效,上电复位 |
(2)网络物理层连接
-
网络变压器 :采用HR911105A (带网络指示灯),连接DM9051的TXP/TXN 、RXP/RXN引脚,中心抽头接3.3V和GND(通过100nF电容隔直)。
-
RJ45接口 :连接网络变压器,加TVS管(如SMAJ5.0A) 防静电,加LED指示灯(连接DM9051的LED引脚,显示连接状态)。
3. 电路设计要点
-
电源滤波 :DM9051的VCC引脚旁加10μF电解电容+100nF瓷片电容,抑制电源噪声。
-
SPI时序 :STM32的SPI配置为主模式、8位数据、CPOL=0、CPHA=0,时钟频率≤10MHz(DM9051支持最高20MHz)。
-
中断处理:INT引脚接STM32的外部中断线(如EXTI0),下降沿触发,在中断服务函数中读取DM9051的接收缓冲区。
三、软件设计
1. 开发环境
-
IDE:Keil MDK-ARM(V5.38)
-
协议栈:LwIP(轻量级TCP/IP,V2.1.3)
-
驱动库:STM32标准外设库(V3.5.0)
2. 软件架构
API调用
数据收发
SPI通信
GPIO/EXTI
MII
应用层
LwIP协议栈
DM9051驱动
STM32硬件层
DM9051芯片
网络变压器+RJ45
3. 关键代码实现
(1)DM9051驱动初始化
c
#include "dm9051.h"
#include "spi.h"
#include "stm32f10x_gpio.h"
// DM9051寄存器地址
#define DM9051_NCR 0x00 // 网络控制寄存器
#define DM9051_TCR 0x01 // 发送控制寄存器
#define DM9051_RCR 0x05 // 接收控制寄存器
#define DM9051_MAC_ADDR 0x0A // MAC地址寄存器(6字节)
#define DM9051_PHY 0x10 // PHY控制寄存器
// DM9051初始化
void DM9051_Init(void) {
// 1. 硬件复位
GPIO_ResetBits(GPIOB, GPIO_Pin_1); // RST=0
Delay_ms(10);
GPIO_SetBits(GPIOB, GPIO_Pin_1); // RST=1
Delay_ms(100);
// 2. 读取芯片ID(0x9051)
uint16_t id = DM9051_ReadReg(DM9051_VIDL) | (DM9051_ReadReg(DM9051_VIDH) << 8);
if (id != 0x9051) { /* 错误处理 */ }
// 3. 配置MAC地址(示例:00:E0:4C:12:34:56)
uint8_t mac[6] = {0x00, 0xE0, 0x4C, 0x12, 0x34, 0x56};
for (int i=0; i<6; i++) {
DM9051_WriteReg(DM9051_MAC_ADDR + i, mac[i]);
}
// 4. 配置接收控制寄存器(RCR)
DM9051_WriteReg(DM9051_RCR, 0x2F); // 接收使能,广播/多播/单播都接收
// 5. 配置发送控制寄存器(TCR)
DM9051_WriteReg(DM9051_TCR, 0x00); // 正常发送模式
// 6. 使能中断(INT)
DM9051_WriteReg(DM9051_IMR, 0x01); // 使能接收中断
}
(2)SPI读写函数
c
// SPI写1字节
void DM9051_WriteReg(uint8_t reg, uint8_t data) {
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // CS=0
SPI1_Write(reg | 0x80); // 写寄存器(最高位1)
SPI1_Write(data);
GPIO_SetBits(GPIOA, GPIO_Pin_4); // CS=1
}
// SPI读1字节
uint8_t DM9051_ReadReg(uint8_t reg) {
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // CS=0
SPI1_Write(reg & 0x7F); // 读寄存器(最高位0)
uint8_t data = SPI1_Read();
GPIO_SetBits(GPIOA, GPIO_Pin_4); // CS=1
return data;
}
(3)LwIP协议栈移植
-
配置LwIP :在
lwipopts.h中设置内存大小、网络参数:c#define MEM_SIZE (8 * 1024) // 内存池大小(8KB) #define TCP_MSS 1460 // TCP最大段大小 #define IP_ADDR "192.168.1.100" // 本机IP #define NETMASK "255.255.255.0" // 子网掩码 #define GW_ADDR "192.168.1.1" // 网关 -
初始化LwIP:
c#include "lwip/init.h" #include "lwip/netif.h" #include "netif/ethernetif.h" struct netif netif; // 网络接口结构体 void LwIP_Init(void) { lwip_init(); // 初始化LwIP协议栈 // 添加网络接口(DM9051驱动) struct ip_addr 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(&netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input); netif_set_default(&netif); // 设置默认网络接口 netif_set_up(&netif); // 启动网络接口 }
(4)TCP服务器示例
c
#include "lwip/tcp.h"
#include "lwip/err.h"
// TCP连接回调函数
static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
if (p != NULL) {
// 回显数据
tcp_write(tpcb, p->payload, p->len, 1);
tcp_output(tpcb);
pbuf_free(p); // 释放pbuf
} else {
// 连接关闭
tcp_close(tpcb);
}
return ERR_OK;
}
// TCP服务器初始化
void TCP_Server_Init(void) {
struct tcp_pcb *tpcb = tcp_new(); // 创建TCP控制块
tcp_bind(tpcb, IP_ADDR_ANY, 8080); // 绑定端口8080
tpcb = tcp_listen(tpcb); // 监听连接
tcp_accept(tpcb, tcp_server_recv); // 设置接收回调
}
参考代码 STM32F103C8T6+DM9051实现以太网功能 www.youwenfan.com/contentcsu/160933.html
四、系统测试
1. 测试工具
-
网络调试助手(如NetAssist):测试TCP/UDP通信
-
Ping命令 :测试网络连通性(如
ping 192.168.1.100) -
Wireshark:抓包分析网络数据
2. 测试步骤
-
硬件检查:用万用表测量3.3V电源、SPI信号是否正常,网络变压器指示灯是否亮。
-
驱动测试:读取DM9051的ID寄存器(0x9051),确认通信正常。
-
LwIP测试 :通过
netif结构体查看IP地址、子网掩码是否正确。 -
应用测试:用TCP客户端连接开发板的8080端口,发送数据,观察是否回显。
五、优化与注意事项
1. 性能优化
-
SPI速率:提高SPI时钟至18MHz(DM9051支持最高20MHz),加快数据收发。
-
LwIP配置 :使用静态内存分配 (
MEM_LIBC_MALLOC=0),减少堆内存碎片。 -
中断优先级 :将DM9051的中断优先级设为高(如NVIC_PriorityGroup_2,抢占优先级1),确保数据及时处理。
2. 常见问题解决
-
无法连接网络:检查MAC地址、IP地址是否冲突,网络变压器是否接反(TX/RX是否交叉)。
-
数据丢包 :增大LwIP的接收缓冲区(
PBUF_POOL_SIZE),或在DM9051中开启FIFO溢出保护。 -
SPI通信错误:用示波器测量SPI的SCK、MOSI、MISO信号,确认时序是否符合DM9051要求(模式0,CPOL=0,CPHA=0)。
六、总结
本设计通过STM32F103C8T6+DM9051+SPI实现了以太网功能,结合LwIP协议栈支持TCP/IP通信,具备低成本、低功耗、易扩展特点。系统可进一步扩展为Web服务器(通过HTTP协议)、MQTT客户端(连接云平台),适用于工业物联网、智能家居等场景。