开发板:

杜邦线传输高速数字信号容易出错,所以在用面包板搭建开发环境时,最好使用25MHz时钟的MII接口。如果要用50MHz的RMII接口,那么杜邦线必须要非常非常短,否则时钟信号一旦失真,就无法收发数据!
如果DP83848的运行时钟是由单片机的PA8 MCO引脚输出的,那么DP83848的复位引脚一定要接一个下拉电阻。当单片机没有启动的时候,这个下拉电阻会使DP83848处于复位状态。因为单片机没有运行的时候,DP83848没有时钟信号,如果此时DP83848没有处于复位状态,将会对电路产生很大的影响!比如启动时单片机的串口输出会乱码。
网口的灯不要接反了,黄灯接LED_ACT,绿灯接LED_LINK。插了网线后,正常情况下是黄灯闪烁,绿灯常亮。
程序里面的USE_MII宏决定了是使用MII接口还是RMII接口。ETH_REMAP宏决定了是否重映射ETH引脚。
#define ETH_REMAP 1
#define USE_MII 0
DP83848的复位引脚接到PB15上(带外部下拉电阻),中断引脚接到PB14上(带外部上拉电阻)。
【代码讲解】
程序里面使用的lwip2.1.2除了下面几个文件是修改过的以外,其余的都是官网的原始文件:
修改的文件:ethernetif.c(修改前的原始文件位于contrib-2.1.0.zip)
添加的文件:arch/cc.h lwipopts.h
(lwip 2.0.3版本中的ethernetif.c文件位于lwip-2.0.3.zip压缩包的src/netif文件夹下。而lwip 2.1.0~2.1.2版本中的ethernetif.c文件则被移动到了contrib-2.1.0.zip压缩包的examples/ethernetif文件夹里面了, 里面有一些细微的修改)
系统时钟的配置是在clock_init函数里面完成的:
// 配置系统和总线时钟
void clock_init(void)
{
HAL_StatusTypeDef status;
RCC_ClkInitTypeDef clk = {0};
RCC_OscInitTypeDef osc = {0};
osc.OscillatorType = RCC_OSCILLATORTYPE_HSE;
osc.HSEPredivValue = RCC_HSE_PREDIV_DIV5;
osc.HSEState = RCC_HSE_ON;
osc.PLL.PLLMUL = RCC_PLL_MUL9;
osc.PLL.PLLSource = RCC_PLLSOURCE_HSE;
osc.PLL.PLLState = RCC_PLL_ON;
osc.PLL2.HSEPrediv2Value = RCC_HSE_PREDIV2_DIV5;
osc.PLL2.PLL2MUL = RCC_PLL2_MUL8;
osc.PLL2.PLL2State = RCC_PLL2_ON;
osc.Prediv1Source = RCC_PREDIV1_SOURCE_PLL2;
status = HAL_RCC_OscConfig(&osc);
assert_param(status == HAL_OK);
// ADC时钟不能超过14MHz, 所以需要6分频, 72MHz经过分频后是12MHz
__HAL_RCC_ADC_CONFIG(RCC_ADCPCLK2_DIV6);
// 配置AHB和APB2总线时钟为72MHz, APB1总线时钟为36MHz
clk.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clk.AHBCLKDivider = RCC_SYSCLK_DIV1;
clk.APB1CLKDivider = RCC_HCLK_DIV2;
clk.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_2);
}
该函数将系统时钟配置为72MHz:AHB和APB2时钟为72MHz,APB1时钟为36MHz。
初始化DP83848的函数是DP83848_Init,该函数是在netif_add添加网卡时调用的,调用关系如下:
main -> net_config -> netif_add(或netif_add_noaddr) -> ethernetif_init -> low_level_init -> DP83848_Init
其中,low_level_init函数的代码如下:
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void
low_level_init(struct netif *netif)
{
//struct ethernetif *ethernetif = netif->state;
int ret;
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set MAC hardware address */
ret = DP83848_Init();
DP83848_GetMACAddress(netif->hwaddr);
printf("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5]);
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_MLD6; // 这里MLD6是启用IPv6多播
if (ret == 0)
netif->flags |= NETIF_FLAG_LINK_UP; // 只有插了网线, 才设置这个标志
#if LWIP_IPV6 && LWIP_IPV6_MLD
/*
* For hardware/netifs that implement MAC filtering.
* All-nodes link-local is handled by default, so we must let the hardware know
* to allow multicast packets in.
* Should set mld_mac_filter previously. */
if (netif->mld_mac_filter != NULL) {
ip6_addr_t ip6_allnodes_ll;
ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
}
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
/* Do whatever else is needed to initialize interface. */
}
在这个函数里面,调用了DP83848_Init初始化网口。如果此时板子是插了网线的,那么函数返回0,没有插网线时返回-1。接着调用DP83848_GetMACAddress将网卡地址(在程序中由STM32单片机的器件ID生成)告诉lwip。接下来,如果插了网线(ret==0),则设置NETIF_FLAG_LINK_UP标志,告诉lwip网卡现在有网,这个操作和netif_set_link_up是等价的。NETIF_FLAG_MLD6表示启用IPv6多播功能,IPv6的运行依赖于多播,不打开多播的话IPv6是不能正常工作的。
接下来看看DP83848_Init函数:
int DP83848_Init(void)
{
uint32_t uid;
ETH_MACInitTypeDef macconf = {0};
GPIO_InitTypeDef gpio;
HAL_Sta

本文详细介绍了如何在STM32微控制器上配置DP83848以太网控制器,包括时钟设置、GPIO初始化、MII/RMII接口选择、MAC地址生成、中断处理和DP83848初始化函数。还讲解了 lwip 网络协议栈的初始化过程,如设置IP地址、启动DHCP、创建IPv6本地链路地址以及处理数据包发送和接收。最后展示了程序运行时的输出结果,包括DHCP获取IP地址、网线插拔中断处理和网络通信功能。
最低0.47元/天 解锁文章
1万+





