一、概述

单片机芯片采用STM32F407VGT6,移植正点原子的以太网demo程序,网口芯片选用RTL8201F,模式采用MII。

二、工程移植

(1)使用CubeMx勾选ETH,模式选择MII(根据硬件设计进行选择,本人使用MII)。之后生成工程文件。

(2)移植程序:

①根据正点原子:lwIP开发指南_V1.7手册,将程序移植到自己的工程中,具体流程如下:将Middlewares文件夹放在在工程文件下,并在工程中导入.c文件:

②修改生成的eth.c工程文件:将正点原子的ethernet.c和ethernet.h替换生成的eth.c和eth.h,但是保留void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle)函数相关内容。

uint32_t phy_id1=0,phy_id2=0;
void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(ethHandle->Instance==ETH)
  {
  /* USER CODE BEGIN ETH_MspInit 0 */

  /* USER CODE END ETH_MspInit 0 */
    /* ETH clock enable */
    __HAL_RCC_ETH_CLK_ENABLE();
		__HAL_RCC_SYSCFG_CLK_ENABLE();

    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**ETH GPIO Configuration
    PE2     ------> ETH_TXD3
    PC1     ------> ETH_MDC
    PC2     ------> ETH_TXD2
    PC3     ------> ETH_TX_CLK
    PA0-WKUP     ------> ETH_CRS
    PA1     ------> ETH_RX_CLK
    PA2     ------> ETH_MDIO
    PA3     ------> ETH_COL
    PA7     ------> ETH_RX_DV
    PC4     ------> ETH_RXD0
    PC5     ------> ETH_RXD1
    PB0     ------> ETH_RXD2
    PB1     ------> ETH_RXD3
    PB11     ------> ETH_TX_EN
    PB12     ------> ETH_TXD0
    PB13     ------> ETH_TXD1

    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4
                          |GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12
                          |GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
				
	ETHERNET_RST(0);                                      
    delay_ms(50);
    ETHERNET_RST(1);                                      
	delay_ms(500);
		
	HAL_ETH_ReadPHYRegister(ethHandle,0x02, &phy_id1);  //RTL8201F ID1: 0x001C
	HAL_ETH_ReadPHYRegister(ethHandle,0x03, &phy_id2);  //RTL8201F ID2: 0xC816
		
    /* ETH interrupt Init */
    HAL_NVIC_SetPriority(ETH_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(ETH_IRQn);
  /* USER CODE BEGIN ETH_MspInit 1 */

  /* USER CODE END ETH_MspInit 1 */
  }
}

③在主函数中调用:

  ·············	
    //lwip
	lwip_comm_init();
	ethernet_read_phy(PHY_SR);
#if LWIP_DHCP    
    while ((g_lwipdev.dhcpstatus != 2) && (g_lwipdev.dhcpstatus != 0XFF))   
    {
        lwip_periodic_handle();
    }
#endif	

  while (1)
  {
		lwip_periodic_handle(); /* LWIP */
  }
··············

三、调试程序:

(1)测试是否可以对网口芯片寄存器操作:

首先,需要先对芯片PHYRSTB拉低至少10ms对RTL8201F进行复位操作:

ETHERNET_RST(0);                                        
delay_ms(50);
ETHERNET_RST(1);                                        
delay_ms(500);

其次,通过MDIO和MDC引脚,对RTL8201F寄存器进行读操作,结果如下注释则说明读取成功。

HAL_ETH_ReadPHYRegister(ethHandle,0x02, &phy_id1);  // RTL8201F ID1: 0x001C
HAL_ETH_ReadPHYRegister(ethHandle,0x03, &phy_id2);  // RTL8201F ID2: 0xC816

(2)测试过程中发现初始化出错,调试发现主要位于HAL_ETH_Init函数等待软件复位过程中:

  /* Wait for software reset */
  while (((heth->Instance)->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET)
  {
    /* Check for the Timeout */
    if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_SWRESET)
    {     
      heth->State= HAL_ETH_STATE_TIMEOUT;
  
      /* Process Unlocked */
      __HAL_UNLOCK(heth);
    
      /* Note: The SWR is not performed if the ETH_RX_CLK or the ETH_TX_CLK are  
         not available, please check your external PHY or the IO configuration */
      return HAL_TIMEOUT;
    }
  }

通过在网上查找看到有博主是时钟出错,类似此博主:

RTL8201 以太网PHY芯片 调试记录-CSDN博客

但是我测量了PHY芯片时钟以及外部时钟产生的波形,并未发现异常。

(MII是25M的晶振,RMII是50M,不要弄错了)

重新查看芯片手册发现:8脚用于判断模式选择MII/RMII,硬件设计时给外部接了上拉电阻,将上拉去掉后就解决这个问题啦!!

(3)现在可以link上了,但是遇到了新的问题,ping不通。

通过检测发现,是连接单片机网口的主机ip未和单片机设置在一个网关下面,所以ping不通。

例如:

单片机如下设置:

    /*默认远端IP:192.168.11.10 */
    lwipx->remoteip[0] = 192;
    lwipx->remoteip[1] = 168;
    lwipx->remoteip[2] = 11;
    lwipx->remoteip[3] = 10;
    
    /* MAC地址 */
    lwipx->mac[0] = 0xB8;
    lwipx->mac[1] = 0xAE;
    lwipx->mac[2] = 0x1D;
    lwipx->mac[3] = 0x00;
    lwipx->mac[4] = 0x01;
    lwipx->mac[5] = 0x00;
    
    /* 默认本地IP:192.168.11.30 */
    lwipx->ip[0] = 192;
    lwipx->ip[1] = 168;
    lwipx->ip[2] = 11;
    lwipx->ip[3] = 30;
    /* 默认子网掩码ë:255.255.255.0 */
    lwipx->netmask[0] = 255;
    lwipx->netmask[1] = 255;
    lwipx->netmask[2] = 255;
    lwipx->netmask[3] = 0;
    
    /* 默认网关:192.168.11.1 */
    lwipx->gateway[0] = 192;
    lwipx->gateway[1] = 168;
    lwipx->gateway[2] = 11;
    lwipx->gateway[3] = 1;
    lwipx->dhcpstatus = 0; /* ûÓÐDHCP */

电脑端配置如下:

四、调试结果

可以ping通了,结果如下:

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐