STM32连接以太网失败自动重新连接

连接失败LED0不亮,连接成功LED0亮;

STM32连接以太网失败自动重新连接

连上之后,断开也可以自动重连,我想创建一个任务,这个任务专门来连接网络,然后在芯片上电的时候,先执行这个任务,这个任务

程序刚进入进行开始创建一个函数任务(想象成手机开机键),然后这个函数开始创建注册函数任务(负责可以让任务可以创建执行),第一个任务是连接tcp(要去一:自动连接tcp)

tcp任务

就是检测tcp是否连接成功是一个任务每一段时间都要进行的:如果未连接上,LED0亮,没有连接上就尝试去连接,直到连接成功,LED0熄灭;如果连接上,LED0灭;如果通信成功就创建开始创建的任务,如果没有创建成功就杀死所有任务,也就是只进行这个连接tcp的任务;

void freertos_demo(void)

{

/* start_task任务 */

xTaskCreate((TaskFunction_t )start_task,

(const char * )"start_task",

(uint16_t )START_STK_SIZE,

(void * )NULL,

(UBaseType_t )START_TASK_PRIO,

(TaskHandle_t * )&StartTask_Handler);

vTaskStartScheduler(); /* 开启任务调度 */

}

这个demo里面创建的任务是tcp,然后这个start_task任务当tcp连接成功的时候创建;

创建任务

复制代码
/**
 ****************************************************************************************************
 * @file        freertos_demo.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2022-01-11
 * @brief       lwIP Netconn TCPServer 实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 探索者 F407开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */
 
#include "freertos_demo.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
#include "./BSP/KEY/key.h"
#include "lwip_comm.h"
#include "lwip_demo.h"
#include "lwipopts.h"
#include "stdio.h"
#include "string.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"


/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         5           /* 任务优先级 */
#define START_STK_SIZE          128         /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler;             /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* LWIP_DEMO 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define LWIP_DMEO_TASK_PRIO     11          /* 任务优先级 */
#define LWIP_DMEO_STK_SIZE      1024        /* 任务堆栈大小 */
TaskHandle_t LWIP_Task_Handler;             /* 任务句柄 */
void lwip_demo_task(void *pvParameters);    /* 任务函数 */

/* LED_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define LED_TASK_PRIO           10          /* 任务优先级 */
#define LED_STK_SIZE            128         /* 任务堆栈大小 */
TaskHandle_t LEDTask_Handler;               /* 任务句柄 */
void led_task(void *pvParameters);          /* 任务函数 */

/* KEY_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define KEY_TASK_PRIO           11          /* 任务优先级 */
#define KEY_STK_SIZE            128         /* 任务堆栈大小 */
TaskHandle_t KEYTask_Handler;               /* 任务句柄 */
void key_task(void *pvParameters);          /* 任务函数 */

/* DISPLAY_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define DISPLAY_TASK_PRIO       12          /* 任务优先级 */
#define DISPLAY_STK_SIZE        512         /* 任务堆栈大小 */
TaskHandle_t DISPLAYTask_Handler;           /* 任务句柄 */
void display_task(void *pvParameters);      /* 任务函数 */

/* NETWORK_STATUS_TASK 网络状态检测任务 配置
 * 包括: 任务句柄、优先级、堆栈大小、任务函数声明
 */
#define NETWORK_STATUS_TASK_PRIO      11       /* 任务优先级(适中) */
#define NETWORK_STATUS_STK_SIZE       1024     /* 任务堆栈大小 */
TaskHandle_t NetworkStatusTask_Handler;       /* 任务句柄 */

void network_status_task(void *pvParameters); /* 任务函数声明 */


/* 显示消息队列的数量 */
#define DISPLAYMSG_Q_NUM    20   /* 显示消息队列的数量 */
QueueHandle_t g_display_queue;     /* 显示消息队列句柄 */

/******************************************************************************************************/


/**
 * @breif       加载UI
 * @param       mode :  bit0:0,不加载;1,加载前半部分UI
 *                      bit1:0,不加载;1,加载后半部分UI
 * @retval      无
 */
void lwip_test_ui(uint8_t mode)
{
    uint8_t speed;
    uint8_t buf[30];
    
    if (mode & 1<< 0)
    {
        lcd_show_string(6, 10, 200, 32, 32, "STM32", DARKBLUE);
        lcd_show_string(6, 40, lcddev.width, 24, 24, "lwIP TCPServer Test", DARKBLUE);
        lcd_show_string(6, 70, 200, 16, 16, "ATOM@ALIENTEK", DARKBLUE);
    }
    
    if (mode & 1 << 1)
    {
        lcd_show_string(5, 110, 200, 16, 16, "lwIP Init Successed", MAGENTA);
        
        if (g_lwipdev.dhcpstatus == 2)
        {
            sprintf((char*)buf,"DHCP IP:%d.%d.%d.%d",g_lwipdev.ip[0],g_lwipdev.ip[1],g_lwipdev.ip[2],g_lwipdev.ip[3]);     /* 显示动态IP地址 */
        }
        else
        {
            sprintf((char*)buf,"Static IP:%d.%d.%d.%d",g_lwipdev.ip[0],g_lwipdev.ip[1],g_lwipdev.ip[2],g_lwipdev.ip[3]);    /* 打印静态IP地址 */
        }
        
        lcd_show_string(5, 130, 200, 16, 16, (char*)buf, MAGENTA);
        
        speed = ethernet_chip_get_speed();      /* 得到网速 */
        
        if (speed)
        {
            lcd_show_string(5, 150, 200, 16, 16, "Ethernet Speed:100M", MAGENTA);
        }
        else
        {
            lcd_show_string(5, 150, 200, 16, 16, "Ethernet Speed:10M", MAGENTA);
        }
        
        lcd_show_string(5, 170, 200, 16, 16, "KEY0:Send data", MAGENTA);
        lcd_show_string(5, 190, lcddev.width - 30, lcddev.height - 190, 16, "Receive Data:", BLUE); /* 提示消息 */
    }
}

/**
 * @breif       freertos_demo
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    /* start_task任务 */
    xTaskCreate((TaskFunction_t )start_task,
                (const char *   )"start_task",
                (uint16_t       )START_STK_SIZE,
                (void *         )NULL,
                (UBaseType_t    )START_TASK_PRIO,
                (TaskHandle_t * )&StartTask_Handler);

    vTaskStartScheduler(); /* 开启任务调度 */
}

/**
 * @brief       start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    pvParameters = pvParameters;/* 防止编译器警告(未使用参数),这行没实际意义 */
    
    g_lwipdev.lwip_display_fn = lwip_test_ui;
    
    lwip_test_ui(1);    /* 加载后前部分UI */
	
    while (1)
    {
         LED0_ON;
        /* 尝试初始化lwIP */
        if (lwip_comm_init() == 0)
        {
            printf("lwIP 初始化成功!\r\n");
            break;  /* 成功则跳出循环 */
        }

        /* 检查PHY是否连接 */
        if (ethernet_read_phy(PHY_SR))
        {
            printf("检测到PHY芯片响应,准备重新初始化...\r\n");
        }
        else
        {
            printf("PHY芯片未响应,等待连接...\r\n");
					LED0_OFF;
        }
				
        vTaskDelay(1000);  /* 每1秒检测一次 */
    }
    
    while((g_lwipdev.dhcpstatus != 2)&&(g_lwipdev.dhcpstatus != 0XFF))  /* 等待DHCP获取成功/超时溢出 */
    {
        vTaskDelay(5);
    }
    

    
    taskENTER_CRITICAL();           /* 进入临界区 */
    
    g_display_queue = xQueueCreate(DISPLAYMSG_Q_NUM,200);      /* 创建消息Message_Queue,队列项长度是200长度 */
		
		/* 网络连接状态检测任务 */
    xTaskCreate((TaskFunction_t )network_status_task,
            (const char*    )"network_status_task",
            (uint16_t       )NETWORK_STATUS_STK_SIZE, 
            (void*          )NULL,
            (UBaseType_t    )NETWORK_STATUS_TASK_PRIO,   // 优先级适中
            (TaskHandle_t*  )NetworkStatusTask_Handler);

//    
//    /* 创建lwIP任务 */
//    xTaskCreate((TaskFunction_t )lwip_demo_task,
//                (const char*    )"lwip_demo_task",
//                (uint16_t       )LWIP_DMEO_STK_SIZE, 
//                (void*          )NULL,
//                (UBaseType_t    )LWIP_DMEO_TASK_PRIO,
//                (TaskHandle_t*  )&LWIP_Task_Handler);

//    /* key任务 */
//    xTaskCreate((TaskFunction_t )key_task,
//                (const char *   )"key_task",
//                (uint16_t       )KEY_STK_SIZE,
//                (void *         )NULL,
//                (UBaseType_t    )KEY_TASK_PRIO,
//                (TaskHandle_t * )&KEYTask_Handler);

//    /* LED测试任务 */
//    xTaskCreate((TaskFunction_t )led_task,
//                (const char*    )"led_task",
//                (uint16_t       )LED_STK_SIZE,
//                (void*          )NULL,
//                (UBaseType_t    )LED_TASK_PRIO,
//                (TaskHandle_t*  )&LEDTask_Handler);

//    /* 显示任务 */
//    xTaskCreate((TaskFunction_t )display_task,
//                (const char*    )"display_task",
//                (uint16_t       )DISPLAY_STK_SIZE,
//                (void*          )NULL,
//                (UBaseType_t    )DISPLAY_TASK_PRIO,
//                (TaskHandle_t*  )&DISPLAYTask_Handler);

    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
    
}

/**
 * @brief       lwIP运行例程
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void lwip_demo_task(void *pvParameters)
{
    pvParameters = pvParameters;

    lwip_demo();            /* lwip测试代码 */
    
    while(1)
    {
        vTaskDelay(5);
    }
}

/**
 * @brief       key_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void key_task(void *pvParameters)
{
    pvParameters = pvParameters;
    
    uint8_t key;
  
    while (1)
    {
        key = key_scan(0);

        if (KEY0_PRES ==key)
        {
            g_lwip_send_flag |= LWIP_SEND_DATA; /* 标记LWIP有数据要发送 */
        }
        
        vTaskDelay(10);
    }
}

/**
 * @brief       系统再运行
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void led_task(void *pvParameters)
{
    pvParameters = pvParameters;

    while(1)
    {
		//	 LED0_TOGGLE(); 
        LED1_TOGGLE();
        vTaskDelay(100);
    }
}

/**
 * @brief       显示任务
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void display_task(void *pvParameters)
{
    pvParameters = pvParameters;
    uint8_t *buffer;
    
    while(1)
    {
        buffer = mymalloc(SRAMIN,200);
        
        if(g_display_queue != NULL)
        {
            memset(buffer,0,200);       /* 清除缓冲区 */
            
            if (xQueueReceive(g_display_queue,buffer,portMAX_DELAY))
            {
                lcd_fill(30, 220, lcddev.width - 1, lcddev.height - 1, WHITE); /* 清上一次数据 */
                /* 显示接收到的数据 */
                lcd_show_string(30, 220, lcddev.width - 30, lcddev.height - 230, 16, (char *)buffer, RED); 
            }
        }
        
        myfree(SRAMIN,buffer);          /*释放内存 */
        
        vTaskDelay(5);
    }
}

void network_status_task(void *pvParameters)
{
    pvParameters = pvParameters;

    while (1)
    {
        uint16_t phy_reg = ethernet_read_phy(PHY_SR);
        uint8_t link_status = (phy_reg & (1 << 2)) ? 0 : 1; // 1=连接, 0=断开

        if (link_status) // 连接上:关闭 LED0
        {
            LED0_OFF;
            printf("网络连接成功\r\n");
        }
        else // 未连接:打开 LED0,并重新初始化 lwIP
        {
            LED0_ON;
            printf("网络断开\r\n");
            lwip_comm_init();
			  }
        vTaskDelay(500); // 每 500ms 检查一次
    }
}


/**
 ****************************************************************************************************
 * @file        lwip_comm.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2021-12-02
 * @brief       LWIP配置驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 探索者 F407开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 * 修改说明
 * V1.0 20211202
 * 第一次发布
 *
 ****************************************************************************************************
 */
 
#include "lwip_comm.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/init.h"
#include "ethernetif.h"
#include "lwip/timeouts.h"
#include "lwip/tcpip.h"
#include "./MALLOC/malloc.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include <stdio.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"


__lwip_dev g_lwipdev;                   /* lwip控制结构体 */
struct netif g_lwip_netif;              /* 定义一个全局的网络接口 */

#if LWIP_DHCP
__IO uint8_t g_lwip_dhcp_state = LWIP_DHCP_OFF;         /* DHCP状态初始化 */
#endif

/* LINK线程配置 */
#define LWIP_LINK_TASK_PRIO             3                   /* 任务优先级 */
#define LWIP_LINK_STK_SIZE              128 * 2             /* 任务堆栈大小 */
void lwip_link_thread( void * argument );                   /* 链路线程 */

/* DHCP线程配置 */
#define LWIP_DHCP_TASK_PRIO             4                   /* 任务优先级 */
#define LWIP_DHCP_STK_SIZE              128 * 2             /* 任务堆栈大小 */
void lwip_periodic_handle(void *argument);                  /* DHCP线程 */
void lwip_link_status_updated(struct netif *netif);         /* DHCP状态回调函数 */

/**
 * @breif       lwip 默认IP设置
 * @param       lwipx  : lwip控制结构体指针
 * @retval      无
 */
void lwip_comm_default_ip_set(__lwip_dev *lwipx)
{
    /* 默认远端IP为:192.168.1.134 */
    lwipx->remoteip[0] = 192;
    lwipx->remoteip[1] = 168;
    lwipx->remoteip[2] = 1;
    lwipx->remoteip[3] = 30;
    
    /* 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.1.30 */
    lwipx->ip[0] = 192;
    lwipx->ip[1] = 168;
    lwipx->ip[2] = 1;
    lwipx->ip[3] = 33;
    /* 默认子网掩码:255.255.255.0 */
    lwipx->netmask[0] = 255;
    lwipx->netmask[1] = 255;
    lwipx->netmask[2] = 255;
    lwipx->netmask[3] = 0;
    
    /* 默认网关:192.168.1.1 */
    lwipx->gateway[0] = 192;
    lwipx->gateway[1] = 168;
    lwipx->gateway[2] = 1;
    lwipx->gateway[3] = 1;
    lwipx->dhcpstatus = 0; /* 没有DHCP */
}

/**
 * @breif       LWIP初始化(LWIP启动的时候使用)
 * @param       无
 * @retval      0,成功
 *              1,内存错误
 *              2,以太网芯片初始化失败
 *              3,网卡添加失败.
 */
uint8_t lwip_comm_init(void)
{
    uint8_t retry = 0;
    struct netif *netif_init_flag;              /* 调用netif_add()函数时的返回值,用于判断网络初始化是否成功 */
    ip_addr_t ipaddr;                           /* ip地址 */
    ip_addr_t netmask;                          /* 子网掩码 */
    ip_addr_t gw;                               /* 默认网关 */
    
    tcpip_init(NULL, NULL);
    
    if (ethernet_mem_malloc())return 1;         /* 内存申请失败*/

    lwip_comm_default_ip_set(&g_lwipdev);         /* 设置默认IP等信息 */

    while (ethernet_init())                     /* 初始化以太网芯片,如果失败的话就重试5次 */
    {
        retry++;

        if (retry > 5)
        {
            retry = 0;                          /* 以太网芯片初始化失败 */
            return 3;
        }
    }

#if LWIP_DHCP                                   /* 使用动态IP */
    ip_addr_set_zero_ip4(&ipaddr);              /* 对IP地址、子网掩码及网关清零 */
    ip_addr_set_zero_ip4(&netmask);
    ip_addr_set_zero_ip4(&gw);
#else   /* 使用静态IP */
    IP4_ADDR(&ipaddr, g_lwipdev.ip[0], g_lwipdev.ip[1], g_lwipdev.ip[2], g_lwipdev.ip[3]);
    IP4_ADDR(&netmask, g_lwipdev.netmask[0], g_lwipdev.netmask[1], g_lwipdev.netmask[2], g_lwipdev.netmask[3]);
    IP4_ADDR(&gw, g_lwipdev.gateway[0], g_lwipdev.gateway[1], g_lwipdev.gateway[2], g_lwipdev.gateway[3]);
    printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n", g_lwipdev.mac[0], g_lwipdev.mac[1], g_lwipdev.mac[2], g_lwipdev.mac[3], g_lwipdev.mac[4], g_lwipdev.mac[5]);
    printf("静态IP地址........................%d.%d.%d.%d\r\n", g_lwipdev.ip[0], g_lwipdev.ip[1], g_lwipdev.ip[2], g_lwipdev.ip[3]);
    printf("子网掩码..........................%d.%d.%d.%d\r\n", g_lwipdev.netmask[0], g_lwipdev.netmask[1], g_lwipdev.netmask[2], g_lwipdev.netmask[3]);
    printf("默认网关..........................%d.%d.%d.%d\r\n", g_lwipdev.gateway[0], g_lwipdev.gateway[1], g_lwipdev.gateway[2], g_lwipdev.gateway[3]);
    g_lwipdev.dhcpstatus = 0XFF;
#endif  /* 向网卡列表中添加一个网口 */
    netif_init_flag = netif_add(&g_lwip_netif, (const ip_addr_t *)&ipaddr, (const ip_addr_t *)&netmask, (const ip_addr_t *)&gw, NULL, &ethernetif_init, &tcpip_input);


    if (netif_init_flag == NULL)
    {
        return 4;                           /* 网卡添加失败 */
    }
    else                                    /* 网口添加成功后,设置netif为默认值,并且打开netif网口 */
    {
        netif_set_default(&g_lwip_netif);     /* 设置netif为默认网口 */

        if (netif_is_link_up(&g_lwip_netif))
        {
            netif_set_up(&g_lwip_netif);      /* 打开netif网口 */
        }
        else
        {
            netif_set_down(&g_lwip_netif);
        }
        
#if LWIP_NETIF_LINK_CALLBACK
        lwip_link_status_updated(&g_lwip_netif);    /* DHCP链接状态更新函数 */
        netif_set_link_callback(&g_lwip_netif, lwip_link_status_updated);
        /* 查询PHY连接状态任务 */
        sys_thread_new("eth_link",
                       lwip_link_thread,            /* 任务入口函数 */
                       &g_lwip_netif,               /* 任务入口函数参数 */
                       LWIP_LINK_STK_SIZE,          /* 任务栈大小 */
                       LWIP_LINK_TASK_PRIO);        /* 任务的优先级 */
#endif
    }
    
    g_lwipdev.link_status = LWIP_LINK_OFF;          /* 链接标记为0 */
#if LWIP_DHCP                                       /* 如果使用DHCP的话 */
    g_lwipdev.dhcpstatus = 0;                       /* DHCP标记为0 */
    /* DHCP轮询任务 */
    sys_thread_new("eth_dhcp",
                   lwip_periodic_handle,            /* 任务入口函数 */
                   &g_lwip_netif,                   /* 任务入口函数参数 */
                   LWIP_DHCP_STK_SIZE,              /* 任务栈大小 */
                   LWIP_DHCP_TASK_PRIO);            /* 任务的优先级 */
#endif
    return 0;                               /* 操作OK. */
}

/**
 * @brief       通知用户网络接口配置状态
 * @param       netif:网卡控制块
 * @retval      无
 */
void lwip_link_status_updated(struct netif *netif)
{
    if (netif_is_up(netif))
    {
#if LWIP_DHCP
        /* Update DHCP state machine */
        g_lwip_dhcp_state = LWIP_DHCP_START;
        printf ("The network cable is connected \r\n");
#endif /* LWIP_DHCP */
    }
    else
    {
#if LWIP_DHCP
        /* Update DHCP state machine */
        g_lwip_dhcp_state = LWIP_DHCP_LINK_DOWN;
        printf ("The network cable is not connected \r\n");
#endif /* LWIP_DHCP */
    }
}



extern xSemaphoreHandle g_rx_semaphore; /* 定义一个信号量 */
/**
 * @breif       当接收到数据后调用
 * @param       无
 * @retval      无
 */
void lwip_pkt_handle(void)
{
    BaseType_t xHigherPriorityTaskWoken;
    /* 获取信号量 */
    xSemaphoreGiveFromISR(g_rx_semaphore,&xHigherPriorityTaskWoken);/* 释放二值信号量 */
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);                   /* 如果需要的话进行一次任务切换  */
}



/* 如果使能DHCP */
#if LWIP_DHCP

/**
 * @breif       DHCP进程
 * @param       argument:传入的形参
 * @retval      无
 */
void lwip_periodic_handle(void *argument)
{
     struct netif *netif = (struct netif *) argument;
    uint32_t ip = 0;
    uint32_t netmask = 0;
    uint32_t gw = 0;
    struct dhcp *dhcp;
    uint8_t iptxt[20];

    while (1)
    {
        switch (g_lwip_dhcp_state)
        {
            case LWIP_DHCP_START:
            {
                /* 对IP地址、网关地址及子网页码清零操作 */
                ip_addr_set_zero_ip4(&netif->ip_addr);
                ip_addr_set_zero_ip4(&netif->netmask);
                ip_addr_set_zero_ip4(&netif->gw);
                ip_addr_set_zero_ip4(&netif->ip_addr);
                ip_addr_set_zero_ip4(&netif->netmask);
                ip_addr_set_zero_ip4(&netif->gw);
                
                g_lwip_dhcp_state = LWIP_DHCP_WAIT_ADDRESS;
                
                printf ("State: Looking for DHCP server ...\r\n");
                dhcp_start(netif);
            }
            break;
            case LWIP_DHCP_WAIT_ADDRESS:
            {
                if (dhcp_supplied_address(netif))
                {
                    g_lwip_dhcp_state = LWIP_DHCP_ADDRESS_ASSIGNED;
                    
                    ip = g_lwip_netif.ip_addr.addr;       /* 读取新IP地址 */
                    netmask = g_lwip_netif.netmask.addr;  /* 读取子网掩码 */
                    gw = g_lwip_netif.gw.addr;            /* 读取默认网关 */
                    
                    sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
                    printf ("IP address assigned by a DHCP server: %s\r\n", iptxt);
                    
                    if (ip != 0)
                    {
                        g_lwipdev.dhcpstatus = 2;         /* DHCP成功 */
                        printf("网卡en的MAC地址为:................%d.%d.%d.%d.%d.%d\r\n", g_lwipdev.mac[0], g_lwipdev.mac[1], g_lwipdev.mac[2], g_lwipdev.mac[3], g_lwipdev.mac[4], g_lwipdev.mac[5]);
                        /* 解析出通过DHCP获取到的IP地址 */
                        g_lwipdev.ip[3] = (uint8_t)(ip >> 24);
                        g_lwipdev.ip[2] = (uint8_t)(ip >> 16);
                        g_lwipdev.ip[1] = (uint8_t)(ip >> 8);
                        g_lwipdev.ip[0] = (uint8_t)(ip);
                        printf("通过DHCP获取到IP地址..............%d.%d.%d.%d\r\n", g_lwipdev.ip[0], g_lwipdev.ip[1], g_lwipdev.ip[2], g_lwipdev.ip[3]);
                        /* 解析通过DHCP获取到的子网掩码地址 */
                        g_lwipdev.netmask[3] = (uint8_t)(netmask >> 24);
                        g_lwipdev.netmask[2] = (uint8_t)(netmask >> 16);
                        g_lwipdev.netmask[1] = (uint8_t)(netmask >> 8);
                        g_lwipdev.netmask[0] = (uint8_t)(netmask);
                        printf("通过DHCP获取到子网掩码............%d.%d.%d.%d\r\n", g_lwipdev.netmask[0], g_lwipdev.netmask[1], g_lwipdev.netmask[2], g_lwipdev.netmask[3]);
                        /* 解析出通过DHCP获取到的默认网关 */
                        g_lwipdev.gateway[3] = (uint8_t)(gw >> 24);
                        g_lwipdev.gateway[2] = (uint8_t)(gw >> 16);
                        g_lwipdev.gateway[1] = (uint8_t)(gw >> 8);
                        g_lwipdev.gateway[0] = (uint8_t)(gw);
                        printf("通过DHCP获取到的默认网关..........%d.%d.%d.%d\r\n", g_lwipdev.gateway[0], g_lwipdev.gateway[1], g_lwipdev.gateway[2], g_lwipdev.gateway[3]);
                        
                        g_lwipdev.lwip_display_fn(2);
                    }
                }
                else
                {
                    dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);

                    /* DHCP timeout */
                    if (dhcp->tries > LWIP_MAX_DHCP_TRIES)
                    {
                        g_lwip_dhcp_state = LWIP_DHCP_TIMEOUT;
                        g_lwipdev.dhcpstatus = 0XFF;
                        /* 使用静态IP地址 */
                        IP4_ADDR(&(g_lwip_netif.ip_addr), g_lwipdev.ip[0], g_lwipdev.ip[1], g_lwipdev.ip[2], g_lwipdev.ip[3]);
                        IP4_ADDR(&(g_lwip_netif.netmask), g_lwipdev.netmask[0], g_lwipdev.netmask[1], g_lwipdev.netmask[2], g_lwipdev.netmask[3]);
                        IP4_ADDR(&(g_lwip_netif.gw), g_lwipdev.gateway[0], g_lwipdev.gateway[1], g_lwipdev.gateway[2], g_lwipdev.gateway[3]);
                        netif_set_addr(netif, &g_lwip_netif.ip_addr, &g_lwip_netif.netmask, &g_lwip_netif.gw);

                        sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
                        printf ("DHCP Timeout !! \r\n");
                        printf ("Static IP address: %s\r\n", iptxt);
                        g_lwipdev.lwip_display_fn(2);
                    }
                }
            }
            break;
            case LWIP_DHCP_LINK_DOWN:
            {
                g_lwip_dhcp_state = LWIP_DHCP_OFF;
            }
            break;
            default: break;
        }

        /* wait 1000 ms */
        vTaskDelay(1000);
    }
}
#endif

#if LWIP_NETIF_LINK_CALLBACK
/**
  * @brief       检查ETH链路状态,更新netif
  * @param       argument: netif
  * @retval      无
  */
void lwip_link_thread( void * argument )
{
    uint32_t regval = 0;
    struct netif *netif = (struct netif *) argument;
    int link_again_num = 0;

    while(1)
    {
        /* 读取PHY状态寄存器,获取链接信息 */
        HAL_ETH_ReadPHYRegister(&g_eth_handler,PHY_BSR, &regval);

        /* 判断链接状态 */
        if((regval & PHY_LINKED_STATUS) == 0)
        {
            g_lwipdev.link_status = LWIP_LINK_OFF;
            
            link_again_num ++ ;
            
            if (link_again_num >= 2)                    /* 网线一段时间没有插入 */
            {
                continue;
            }
            else                                        /* 关闭虚拟网卡及以太网中断 */
            {
#if LWIP_DHCP                                           /* 如果使用DHCP的话 */
                g_lwip_dhcp_state = LWIP_DHCP_LINK_DOWN;

                dhcp_stop(netif);
#endif
                HAL_ETH_Stop(&g_eth_handler);
                netif_set_down(netif);
                netif_set_link_down(netif);
            }
        }
        else                                            /* 网线插入检测 */
        {
            link_again_num = 0;

            if (g_lwipdev.link_status == LWIP_LINK_OFF)/* 开启以太网及虚拟网卡 */
            {
                g_lwipdev.link_status = LWIP_LINK_ON;
                HAL_ETH_Start(&g_eth_handler);
                netif_set_up(netif);
                netif_set_link_up(netif);
            }
        }

        vTaskDelay(100);
    }
}
#endif
相关推荐
XINVRY-FPGA1 小时前
XC3S1000-4FGG320I Xilinx AMD Spartan-3 SRAM-based FPGA
嵌入式硬件·机器学习·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
猫猫的小茶馆4 小时前
【ARM】ARM的介绍
c语言·开发语言·arm开发·stm32·单片机·嵌入式硬件·物联网
猫猫的小茶馆4 小时前
【PCB工艺】数模电及射频电路基础
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·pcb工艺
点灯小铭4 小时前
基于单片机的智能药物盒设计与实现
数据库·单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
梓德原4 小时前
【基础】详细分析带隙型稳压电路的工作原理
单片机·嵌入式硬件·物联网
国科安芯5 小时前
航天医疗领域AS32S601芯片的性能分析与适配性探讨
大数据·网络·人工智能·单片机·嵌入式硬件·fpga开发·性能优化
小李做物联网6 小时前
【物联网毕业设计】60.1基于单片机物联网嵌入式项目程序开发之图像厨房监测系统
stm32·单片机·嵌入式硬件·物联网
贝塔实验室7 小时前
新手如何使用Altium Designer创建第一张原理图(三)
arm开发·单片机·嵌入式硬件·fpga开发·射频工程·基带工程·嵌入式实时数据库
@good_good_study7 小时前
STM32 ADC多通道采样实验
stm32·单片机·嵌入式硬件
Darken037 小时前
什么是“位带”?;在STM32单片机中有什么作用?
stm32·单片机·嵌入式硬件