0 工具准备
1.野火 stm32f407霸天虎开发板
2.LAN8720数据手册
3.STM32F4xx中文参考手册
1 MCU管脚配置
1.1 使能外设相关时钟
STM32配置任何外设的第一步都是使能相关的外设时钟,根据前面的原理图我们需要使能相关的引脚时钟,同时我们需要使能SYSCFG时钟,用来选择MII或RMII模式。
(1)使能GPIO时钟
RCC_AHB1PeriphClockCmd(ETH_MDIO_GPIO_CLK | ETH_MDC_GPIO_CLK |
ETH_RMII_REF_CLK_GPIO_CLK | ETH_RMII_CRS_DV_GPIO_CLK |
ETH_RMII_RXD0_GPIO_CLK | ETH_RMII_RXD1_GPIO_CLK |
ETH_RMII_TX_EN_GPIO_CLK | ETH_RMII_TXD0_GPIO_CLK |
ETH_RMII_TXD1_GPIO_CLK,
ENABLE);
(2)使能SYSCFG时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
注意:
使用 SYSCFG_PMC 寄存器中的配置位 23 MII_RMII_SEL 选择 MII 或 RMII 模式。以太网控制器处于复位模式或使能时钟前,应用程序必须设置 MII/RMII 模式。
1.2 选择RMII模式
这里我们选择RMII模式和LAN8720进行通信,语句如下:
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
如果使用其它支持MII的PHY,选择MII模式的语句如下:
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
使用MII时需要生成TX_CLK 和 RX_CLK 时钟信号,必须向外部 PHY 提供 25MHz 时钟。除了使用外部25MHz石英晶振提供时钟外,还可以通过STM32的MCO引脚输出该信号。
为了使STN32的MCO引脚输出25MHz时钟信号,可以使用以下语句:
RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
上面语句的含义是选择HSE作为时钟源,分频系数为1。由于我们使用的HSE时钟信号是25MHz的,因此便可以在MCO上输出25MHz时钟信号。
1.3 配置GPIO管脚
在开启了相关时钟之后,我们需要配置GPIO到所需要的模式,这些GPIO全部被复用为ETH功能,相关语句如下:
/* Configure ETH_MDIO */
GPIO_InitStructure.GPIO_Pin = ETH_MDIO_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(ETH_MDIO_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_MDIO_PORT, ETH_MDIO_SOURCE, ETH_MDIO_AF);
/* Configure ETH_MDC */
GPIO_InitStructure.GPIO_Pin = ETH_MDC_PIN;
GPIO_Init(ETH_MDC_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_MDC_PORT, ETH_MDC_SOURCE, ETH_MDC_AF);
/* Configure ETH_RMII_REF_CLK */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_REF_CLK_PIN;
GPIO_Init(ETH_RMII_REF_CLK_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_REF_CLK_PORT, ETH_RMII_REF_CLK_SOURCE, ETH_RMII_REF_CLK_AF);
/* Configure ETH_RMII_CRS_DV */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_CRS_DV_PIN;
GPIO_Init(ETH_RMII_CRS_DV_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_CRS_DV_PORT, ETH_RMII_CRS_DV_SOURCE, ETH_RMII_CRS_DV_AF);
/* Configure ETH_RMII_RXD0 */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_RXD0_PIN;
GPIO_Init(ETH_RMII_RXD0_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_RXD0_PORT, ETH_RMII_RXD0_SOURCE, ETH_RMII_RXD0_AF);
/* Configure ETH_RMII_RXD1 */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_RXD1_PIN;
GPIO_Init(ETH_RMII_RXD1_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_RXD1_PORT, ETH_RMII_RXD1_SOURCE, ETH_RMII_RXD1_AF);
/* Configure ETH_RMII_TX_EN */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_TX_EN_PIN;
GPIO_Init(ETH_RMII_TX_EN_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_TX_EN_PORT, ETH_RMII_TX_EN_SOURCE, ETH_RMII_TX_EN_AF);
/* Configure ETH_RMII_TXD0 */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_TXD0_PIN;
GPIO_Init(ETH_RMII_TXD0_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_TXD0_PORT, ETH_RMII_TXD0_SOURCE, ETH_RMII_TXD0_AF);
/* Configure ETH_RMII_TXD1 */
GPIO_InitStructure.GPIO_Pin = ETH_RMII_TXD1_PIN;
GPIO_Init(ETH_RMII_TXD1_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(ETH_RMII_TXD1_PORT, ETH_RMII_TXD1_SOURCE, ETH_RMII_TXD1_AF);
2 总结
(1)使能相关时钟(一定要使能SYSCFG时钟)
(2)选择ETH为RMII模式
(3)配置复用引脚为ETH功能