记录STM32F407+CUBEMX+lwip实现检测网线插拔状态

记录STM32F407+CUBEMX+lwip实现检测网线插拔状态

一、 创建CubeMX工程

1.配置ETH外设如下,我使用的PHY芯片为LAN8270,故选择user phy;配置phy芯片寄存器值,默认即可;设置PA8为PHY芯片复位引脚;开启ETH的全局中断
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.配置LWIP协议;使能LWIP;我使用的是静态IP,未用到DHCP;
使能LWIP_NETIF_LINK_CALLBACK选项,使能该选项时,和网线拔掉重连的一些接口函数才会编译,其实质就是一个条件编译选项
在这里插入图片描述
在这里插入图片描述
3.系统时钟配置,STM32的HSE选用的8MHZ的时钟源;PHY芯片的时钟可由STM32的MCO引脚输出,也可单独给PHY芯片一个外部时钟源,我使用的是外部时钟;
在这里插入图片描述

二、生成工程

在这里插入图片描述

三、打开MDK工程,修改mian函数

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_UART5_Init();
  MX_LWIP_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		MX_LWIP_Process();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

在while(1)中添加MX_LWIP_Process()函数;修改MX_LWIP_Process函数;

void MX_LWIP_Process(void)
{
/* USER CODE BEGIN 4_1 */
/* USER CODE END 4_1 */
  ethernetif_input(&gnetif);

/* USER CODE BEGIN 4_2 */
  ethernetif_set_link(&gnetif);//添加该函数
/* USER CODE END 4_2 */
  /* Handle timeouts */
  sys_check_timeouts();

/* USER CODE BEGIN 4_3 */
/* USER CODE END 4_3 */
}

在原本的工程自动生成的MX_LWIP_Process()函数中添加ethernetif_set_link()函数,这个函数会去读取PHY芯片中网口连接状态的寄存器,并更新struct netif网络接口结构体中保存网络连接状态的值。

四 回调函数

当网线拔掉或重插时会触发以下回调函数;
首先在mian函数中调用的MX_LWIP_Init();该函数中会调用 netif_set_link_callback(&gnetif, ethernetif_update_config)函数,这个函数是注册一个回调函数,当网络连接状态发生变化时会执行ethernetif_update_config函数,这个函数原型如下,

void ethernetif_update_config(struct netif *netif)
{
  __IO uint32_t tickstart = 0;
  uint32_t regvalue = 0;

  if(netif_is_link_up(netif))
  {
    /* Restart the auto-negotiation */
    if(heth.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
    {
      /* Enable Auto-Negotiation */
      HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_AUTONEGOTIATION);

      /* Get tick */
      tickstart = HAL_GetTick();

      /* Wait until the auto-negotiation will be completed */
      do
      {
        HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &regvalue);

        /* Check for the Timeout ( 1s ) */
        if((HAL_GetTick() - tickstart ) > 1000)
        {
          /* In case of timeout */
          goto error;
        }
      } while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));

      /* Read the result of the auto-negotiation */
      HAL_ETH_ReadPHYRegister(&heth, PHY_SR, &regvalue);

      /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
      if((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
      {
        /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
        heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
      }
      else
      {
        /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
        heth.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
      }
      /* Configure the MAC with the speed fixed by the auto-negotiation process */
      if(regvalue & PHY_SPEED_STATUS)
      {
        /* Set Ethernet speed to 10M following the auto-negotiation */
        heth.Init.Speed = ETH_SPEED_10M;
      }
      else
      {
        /* Set Ethernet speed to 100M following the auto-negotiation */
        heth.Init.Speed = ETH_SPEED_100M;
      }
    }
    else /* AutoNegotiation Disable */
    {
    error :
      /* Check parameters */
      assert_param(IS_ETH_SPEED(heth.Init.Speed));
      assert_param(IS_ETH_DUPLEX_MODE(heth.Init.DuplexMode));

      /* Set MAC Speed and Duplex Mode to PHY */
      HAL_ETH_WritePHYRegister(&heth, PHY_BCR, ((uint16_t)(heth.Init.DuplexMode >> 3) |
                                                     (uint16_t)(heth.Init.Speed >> 1)));
    }

    /* ETHERNET MAC Re-Configuration */
    HAL_ETH_ConfigMAC(&heth, (ETH_MACInitTypeDef *) NULL);

    /* Restart MAC interface */
    HAL_ETH_Start(&heth);
  }
  else
  {
    /* Stop MAC interface */
    HAL_ETH_Stop(&heth);
  }

  ethernetif_notify_conn_changed(netif);
}

在这个函数末尾调用了一个弱定义函数ethernetif_notify_conn_changed;

__weak void ethernetif_notify_conn_changed(struct netif *netif)

所以只用重写这个函数,就可以检测出网线拔掉或者插上
我的重写如下:

void ethernetif_notify_conn_changed(struct netif *netif) 
{
		if (netif_is_link_up(netif))
		{
			printf("netif is link up\r\n");
			netif_set_up(netif);
		}
		else
		{
			printf("netif set down\r\n");
			netif_set_down(netif);
		}		
}

五 、总结

1 、在MX_LWIP_Process()函数中添加ethernetif_set_link(),完成PHY芯片寄存器网口连接状态的读取,
2. 重写ethernetif_notify_conn_changed()函数,实现自己想要的功能

学习记录 完结~~~~

### STM32F407 CubeMX LwIP 协议栈移植教程 #### 准备工作 为了在STM32F407实现LwIP协议栈的移植,首先需要准备好必要的软件工具和硬件平台。具体来说: - 安装最新版本的STM32CubeMX图形配置工具[^1]。 - 配置Ubuntu 20.04操作系统环境,并安装`arm-none-eabi-gcc`交叉编译器链[^4]。 #### 创建新项目并初始化设置 启动STM32CubeMX后,创建一个新的工程项目,选择目标MCU型号为STM32F407VGT6或其他兼容变体。完成基本参数设定之后进入中间件部分的选择界面。 #### 中间件选型与配置 在中间件选项卡内勾选LwIP v2.x作为TCP/IP堆栈解决方案。此时会自动加载一系列预定义的功能模块和支持库文件到当前工程结构当中。 对于更高级别的定制需求,可以进一步调整如下几个方面: - **网络接口**:指定物理连接方式(如RMII模式下的以太网口),以及对应的PHY芯片驱动程序; - **内存管理**:根据实际应用场景优化缓冲区大小、数量等参数来提高性能表现; - **多线程支持**:如果计划引入RTOS,则需同步考虑任务调度机制对网络数据处理流程的影响;反之,在裸机环境中运行时则要特别注意中断优先级和服务时间窗口的设计[^2]。 #### 生成功程框架代码 当所有必要配置完成后点击“生成代码”按钮让STM32CubeMX自动生成完整的源码目录树及初始化的main函数入口点。此过程还会一并将选定好的外设资源映射关系写入至相应的头文件之中以便后续编程调用方便快捷。 ```c // main.c 示例片段 #include "lwip/opt.h" #include "lwip/init.h" int main(void) { HAL_Init(); SystemClock_Config(); /* 初始化LwIP */ lwip_init(); while (1){ // 主循环逻辑... } } ``` #### 编译链接与烧录调试 最后一步就是将上述准备工作产生的整个应用程序通过Makefile脚本进行编译构建得到最终可执行二进制镜像文件(.hex/.bin),再借助JTAG/SWD调试探针将其刷入到目标板载Flash存储空间里去验证功能是否正常运作了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值