STM32H7单片机通过STM32CUBEMX移植LWIP,DHCP+tcp_client与上位机通信以及网线断开重连和tcp客户端断开重连机制,通信速率测试能到34Mbps

在H743验证成功。

1、针对H743的MPU配置

MPU_InitStruct.Enable = MPU_REGION_ENABLE;

    MPU_InitStruct.Number = MPU_REGION_NUMBER0;

    MPU_InitStruct.BaseAddress = 0x30040000;

    MPU_InitStruct.Size = MPU_REGION_SIZE_256B;

    MPU_InitStruct.SubRegionDisable = 0x0;

    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

    MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;

    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

    MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    /** Initializes and configures the Region and the memory to be protected

    */

    MPU_InitStruct.Number = MPU_REGION_NUMBER1;

    MPU_InitStruct.BaseAddress = 0x30044000;

    MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;

    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;

    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

TX Descriptor   length 4

First TX Descriptor address 0x3004 0080

RX Descriptor length 4

First RX Descriptor address 0x3004 0000

Rx Buffers Address 0x3004 0100

Rx Buffers length 1536

LWIP RAM HEAP   POINTER (RAM Heap Pointer) 0x3004 4000

MEM SIZE (Heap Memory Size) 14336 Byte(s)

#define TCP_MSS 1460

在TCP_Server的基础上直接修改,其实和重新写一样没啥区别。

2、实现思路:

先通过DHCP获取H743的IP地址,然后TCP_client 初始化,再编连接服务器回调函数,数据接收回调函数。下位机接收指令,下位机持续发送数据,网速测试,tcp客户端中断重连。

2.1  TCP_client 初始化包含:创建TCP_client PCB,绑定本地端口和IP地址,连接服务器。

2.2 tcp客户端中断重连:通过判断clientpcb->state 客户端pcb的状态值,如果clinetpcb->state  不等于ESTABLISHED(int 04),终止PCB连接,删除PCB,重新TCP_client 初始化。

我们通过添加err_clinetpcb_state到各个功能代码区域,

在TCP_client 初始化中,连接服务器后添加第一个err_clinetpcb_state查询模块。

/*tcp_pcb的状态*/

            err_clinetpcb_state = clientpcb->state;

            printf("err_clinetpcb_state 0 is:%d \r\n", err_clinetpcb_state);

在连接服务器回调函数中,添加第二个err_clinetpcb_state查询模块。

/*tcp_pcb的状态*/

            err_clinetpcb_state = clientpcb->state;

            printf("err_clinetpcb_state 1 is:%d \r\n", err_clinetpcb_state);

在数据接收回调函数中,添加第三个err_clinetpcb_state查询模块。

 err_clinetpcb_state = clientpcb->state;

    printf("err_clinetpcb_state 2 is:%d \r\n", err_clinetpcb_state);/*tcp_pcb的状态*/

  在while循环,客户端发送数据中,添加第四个err_clinetpcb_state查询模块。

err_clinetpcb_state = clientpcb->state;

            printf("err_clinetpcb_state 3 is:%d \r\n", err_clinetpcb_state);

在while循环中,客户端断开重连中,添加第5个err_clinetpcb_state查询模块。

 err_clinetpcb_state = clientpcb->state;

            printf("err_clinetpcb_state 4 is:%d \r\n", err_clinetpcb_state);

2.3来做个验证。

打开网络助手,网络设置TCP Server

本地主机地址,即上位机的IP地址

本地主机端口,即上位机对应的端口

烧录程序,查看串口助手

743 ipaddress is 192.168.124.46 H743通过DHCP获取地址

bind err status is:0  客户端绑定端口和IP地址成功,

err_tcp_connect status is:0 客户端pcb连接服务器动作成功,

err_clinetpcb_state 0 is:2  此时客户端pcb连接服务器处于三次握手

tcp client connected  此时客户端pcb连接服务器已经成功,

err_clinetpcb_state 1 is:4   此时客户端pcb连接服务器已经处于稳定连接状态

我们从网络助手也看到

tcp client is connected 下位机发给上位机,此时客户端pcb连接服务器已经成功

网络助手发送:start

串口助手接收到:

err_clinetpcb_state 2 is:4    数据接收回调函数收到上位机的指令,此时客户端pcb连接服务器已经处于稳定连接状态

接收缓冲区已经释放   

err_clinetpcb_state 3 is:4  客户端发送数据中,此时客户端pcb连接服务器已经处于稳定连接状态。

此时网络助手接收到下位机发来的数据。

关闭端口,再打开端口,此时串口助手

RX:err_clinetpcb_state 2 is:7   数据接收回调函数收到上位机的指令,此时客户端pcb连接服务器已经处于CLOSE_WAIT= 7,

tcp client closed   此时客户端pcb连接服务器已经处于关闭状态

err_clinetpcb_state 4 is:9  断开端口重连中,此时客户端pcb连接服务器已经处于 LAST_ACK= 9,

bind err status is:0    初始化中绑定端口和IP地址成功

err_tcp_connect status is:0 客户端pcb连接服务器动作成功,

err_clinetpcb_state 0 is:2 初始化此时客户端pcb连接服务器处于三次握手中SYN_SENT= 2,

err_clinetpcb_state 4 is:2  端口断开重新中,此时客户端pcb连接服务器处于三次握手中SYN_SENT= 2,

bind err status is:0 初始化中绑定端口和IP地址成功。

直到端口断开重连完成。

此时网络助手,

可以再次看到tcp client is connected,开始继续接收下位机发来的数据。

2.4 断开网线重连测试

串口助手,提示网线断开。网络助手,停止接收数据。

网线重新插上

网卡状态个更新,打印出IP地址。网络助手,继续接收数据。

完整代码

main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lwip.h"
#include "memorymap.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "lwip/tcp.h"
#include "string.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define TCP_REMOTE_PORT    8881 /* 远端端口 上位机*/

#define TCP_LOCAL_PORT     8880 /* 本地端口 STM32*/

uint32_t num;
uint8_t newipaddress[4];
err_t status_server, status_new;
/* USER CODE END PV */
char rxbuff[2048];
uint32_t address = 0;
uint32_t rx_flag = 0;//接收到上位机指令为1
uint32_t count = 0;
uint32_t init_flag=0;//初始化完成为1
err_t err_clinetpcb_state;


char sendbuffer[] = "20250106hel20250106hello20250106hello20250106hello20250106hello\r\n";
//char sendbuffer[] = "20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello\r\n";
//char sendbuffer[] = "20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello\r\n";
//char sendbuffer[] = "20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello20250106hello\r\n";

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
extern struct netif gnetif;
struct tcp_pcb *tcp_server_pcb;      /* 定义一个TCP服务器控制块 */
struct tcp_pcb *tcppcbnew;          /* 定义一个TCP服务器控制块 */
struct tcp_pcb *clientpcb;       /* 定义一个TCP客户端控制块 */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
int new_flag = 1;
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int c, FILE *stream)    //重写fputc函数
{
    /*
       huart1是工具生成代码定义的UART1结构体,
       如果以后要使用其他串口打印,只需要把这个结构体改成其他UART结构体。
    */
    HAL_UART_Transmit(&huart1, (unsigned char *)&c, 1, 1000);
    return 1;
}
/* USER CODE END PTD */
static err_t TCPServerCallback(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err)
{
    struct pbuf *tcp_send_pbuf;
    char echoString[] = "This is the client content echo:\r\n";
//    rx_flag = 1;
    if (tcp_recv_pbuf != NULL)
    {
        /* 更新接收窗口 */
        tcp_recved(pcb, tcp_recv_pbuf->tot_len);
//
//     /* 将接收的数据拷贝给发送结构体 */
        tcp_send_pbuf = tcp_recv_pbuf;
//          address=&rxbuff;
//        memcpy(rxbuff, tcp_recv_pbuf->payload, 100);
        tcp_write(pcb, echoString, strlen(echoString), 1);
//        count = tcp_sndbuf(pcb); //查询剩余buf大小
//        printf("before payload buffer is %d\r\n", count);
//        printf("before payload status is  %d\r\n", status);
//             printf(" payload length  is  %d\r\n", tcp_send_pbuf->len);
        /* 将接收到的数据再转发出去 */
        status_server = tcp_write(pcb, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);
//
//        count = tcp_sndbuf(pcb); //查询剩余buf大小
//        printf("after payload buffer is  %d\r\n", status);

//        rx_flag = 1;
        printf("after payload buffer is %d\r\n", count);
        pbuf_free(tcp_recv_pbuf);
//        tcp_close(pcb);
    }
//   else if (err == ERR_OK)
//   {
//     return tcp_close(pcb);
//   }

    return ERR_OK;
}
static err_t TCPServerAccept(void *arg, struct tcp_pcb *pcb, err_t err)
{
    /* 确认监听与连接 */
//     tcp_arg(pcb, mem_calloc(sizeof(struct name), 1));

//        /* 发送一个建立连接的字符串 */
//        tcp_write(pcb, "hello my dream \n\r",strlen("hello my dream \n\r  ")-2,1);

//        /* 配置接收回调函数 */
//        tcp_recv(pcb, tcp_server_recv);
    tcp_recv(pcb, TCPServerCallback);
    return ERR_OK;
}



/*****************************************************
* 描述 :数据接收回调函数
* 参数 :——
* 返回 :——
*****************************************************/
static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    uint32_t i;
    /*数据回传*/
    //tcp_write(tpcb,p->payload,p->len,1);
    err_clinetpcb_state = clientpcb->state;
//    printf("err_clinetpcb_state 2 is:%d \r\n", err_clinetpcb_state);/*tcp_pcb的状态*/

    if (p != NULL)
    {
        struct pbuf *ptmp = p;
        rx_flag = 1;//接收到上位机发来的数据,可当作指令
        /*打印接收到的数据*/
//        printf("get msg from %d:%d:%d:%d: port:%d:\r\n", *((uint8_t *)&tpcb->remote_ip.addr),
//               *((uint8_t *)&tpcb->remote_ip.addr + 1), *((uint8_t *)&tpcb->remote_ip.addr + 2),
//               *((uint8_t *)&tpcb->remote_ip.addr + 3), tpcb->remote_port);
//        while (ptmp != NULL)
//        {
//            for (i = 0; i < p->len; i++)
//            {
//                printf("%c", *((char *)p->payload + i));
//                rx_flag = 1;
//            }
//            ptmp = p->next;
//        }
//        printf("\r\n");
//        tcp_recved(tpcb, p->tot_len);
        /*释放缓冲区数据*/
        pbuf_free(p);

       // printf("接收缓冲区已经释放\r\n");
    }
    else if (err == ERR_OK)
    {
        printf("tcp client closed\r\n");

        tcp_recved(tpcb, p->tot_len);

        return tcp_close(tpcb);
    }

    return ERR_OK;

}
/********************************************************
* 描述 :连接服务器回调函数
* 参数:—
* 返回:—
*********************************************************/
static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    printf("tcp client is connected\r\n");             //tcp客户端连接成功
    tcp_write(tpcb, "tcp client is connected\r\n", strlen("tcp client is connected\r\n"), 1); //反馈连接状态给客户端
    err_clinetpcb_state = clientpcb->state;
    printf("err_clinetpcb_state 1 is:%d \r\n", err_clinetpcb_state); /*tcp_pcb的状态*/

    /*注册接收回调函数*/
    tcp_recv(tpcb, tcp_client_recv);
    return ERR_OK;
}

/**********************************
* 描述 :创建tcp客户端
* 参数: 无
* 返回: 无
************************************/
void tcp_client_init(void)
{
    ip_addr_t serverIp;

    /*服务器IP*/
    IP4_ADDR(&serverIp, 192, 168, 124, 48);

    /*创建tcp客户端控制块*/
    clientpcb = tcp_new();
    if (clientpcb != NULL)
    {
        err_t err, err_tcp_connect;

        /*绑定本地端口号和IP地址*/
        err = tcp_bind(clientpcb, IP_ADDR_ANY, TCP_LOCAL_PORT);
        printf("bind err status is:%d \r\n", err);

        if (err == ERR_OK)
        {
            /*连接服务器*/
					init_flag=1;
            err_tcp_connect = tcp_connect(clientpcb, &serverIp, TCP_REMOTE_PORT, tcp_client_connected);
            printf("err_tcp_connect status is:%d \r\n", err_tcp_connect);
						/*tcp_pcb的状态*/
            err_clinetpcb_state = clientpcb->state;
            printf("err_clinetpcb_state 0 is:%d \r\n", err_clinetpcb_state);
        }
        else
        {
            printf("can not bind pcb\r\n");
            memp_free(MEMP_TCP_PCB, clientpcb);
        }
    }
}



/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

    /* MPU Configuration--------------------------------------------------------*/
    MPU_Config();

    /* Enable the CPU Cache */

    /* Enable I-Cache---------------------------------------------------------*/
    SCB_EnableICache();

    /* Enable D-Cache---------------------------------------------------------*/
    SCB_EnableDCache();

    /* 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_USART1_UART_Init();

    /* USER CODE BEGIN 2 */
		//PHY芯片复位
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
    HAL_Delay(50);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
    HAL_Delay(50);
    /* USER CODE END 2 */
    MX_LWIP_Init();
    printf("<<<<<<<<<<<<H743 lwip tcp client test<<<<<<<<<<<<\r\n");
    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (gnetif.ip_addr.addr == 0)
    {
        //DHCP分配的IP地址
        MX_LWIP_Process();
    }
    *(uint32_t *)newipaddress = (gnetif.ip_addr.addr);
    if (new_flag)
    {
        new_flag = 0;

        printf("the new ip address is configing!\r\n");
        printf("743 ipaddress is %d.%d.%d.%d\r\n", newipaddress[0], newipaddress[1], newipaddress[2], newipaddress[3]);
        tcp_client_init();//客户端初始化
//        tcppcbnew = tcp_new();
//        err_t res = tcp_bind(tcppcbnew, IP_ADDR_ANY, 8080);
//        printf(" tcp_bind res is %d\r\n", res);
//        /* 监听之前创建的结构体tcp_server_pcb */
//        tcp_server_pcb = tcp_listen(tcppcbnew);
//           /* 初始化结构体接收回调函数 */
//        tcp_accept(tcp_server_pcb, TCPServerAccept);

    }

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

        /* USER CODE BEGIN 3 */
        MX_LWIP_Process();

//        num++;
//        HAL_Delay(1);
//
//         if(num% 100000 ==0)
//           {
//               printf("ipaddress is %d.%d.%d.%d\r\n", newipaddress[0], newipaddress[1], newipaddress[2], newipaddress[3]);
//            }

//        count = tcp_sndbuf(tcppcbnew); //查询剩余buf大小
//              HAL_Delay(2500);
//            printf("before payload buffer is  %d\r\n", count);
//        if ((count / TCP_MSS) > 1)
//        {
//            tcp_write(tcppcbnew, sendbuffer, strlen(sendbuffer), 1);
//         tcp_output(tcppcbnew);
                   count = tcp_sndbuf(tcppcbnew); //查询剩余buf大小
                    printf("after payload buffer is  %d\r\n", count);
                  HAL_Delay(2500);
//        }
//        else
//        {
//            HAL_Delay(1);
        if ((init_flag==1)&&(rx_flag == 1) && (clientpcb->state == ESTABLISHED))//客户端发送数据
        {
            err_clinetpcb_state = clientpcb->state;
//            printf("err_clinetpcb_state 3 is:%d \r\n", err_clinetpcb_state);
//           HAL_Delay(1000);
            status_new = tcp_write(clientpcb, sendbuffer, strlen(sendbuffer), 1);
            tcp_output(clientpcb);
//           HAL_Delay(5000);
//            rx_flag = 0;

        }
        if ((init_flag==1)&&(rx_flag == 1) && (clientpcb->state != ESTABLISHED))//客户端断开重连
        {
            err_clinetpcb_state = clientpcb->state;
//            printf("err_clinetpcb_state 4 is:%d \r\n", err_clinetpcb_state);
            /* 移除回调 */
					init_flag=0;
            tcp_abort(clientpcb);                        /* 终止连接,删除pcb控制块 */
            tcp_arg(clientpcb, NULL);                    /* 应用程序状态设置函数为空 */
            tcp_recv(clientpcb, NULL);                    /* 提示远程主机已经关闭连接 */
            tcp_sent(clientpcb, NULL);                    /* 确认回调为空 */
            tcp_err(clientpcb, NULL);                    /* 处理错误的回调函数为空 */
            tcp_poll(clientpcb, NULL, 0);                    /* 轮询时间为零 */
            tcp_client_init();
        }
//                  count = tcp_sndbuf(tcppcbnew); //查询剩余buf大小
//                  printf("after payload buffer is  %d\r\n", count);
//                  HAL_Delay(2500);
//        }

//                  printf("after payload buffer is  %d\r\n", count);
//                  HAL_Delay(1000);
//          if(rx_flag==1)
//          {
//           status_new=    tcp_write(tcppcbnew, sendbuffer, strlen(sendbuffer), 1);
//                      printf("tcppcbnew status is %d\r\n",status_new);
//                      rx_flag=0;
//          }


    }
    /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /** Supply configuration update enable
    */
    HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

    /** Configure the main internal regulator output voltage
    */
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

    __HAL_RCC_SYSCFG_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

    while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

    /** Initializes the RCC Oscillators according to the specified parameters
    * in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 1;
    RCC_OscInitStruct.PLL.PLLN = 120;
    RCC_OscInitStruct.PLL.PLLP = 2;
    RCC_OscInitStruct.PLL.PLLQ = 2;
    RCC_OscInitStruct.PLL.PLLR = 2;
    RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
    RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
    RCC_OscInitStruct.PLL.PLLFRACN = 0;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    /** Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2
                                  | RCC_CLOCKTYPE_D3PCLK1 | RCC_CLOCKTYPE_D1PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
    RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
    {
        Error_Handler();
    }
    __HAL_RCC_D2SRAM1_CLK_ENABLE();//对SRAM内存块时钟使能
    __HAL_RCC_D2SRAM2_CLK_ENABLE();
    __HAL_RCC_D2SRAM3_CLK_ENABLE();

    __HAL_RCC_BKPRAM_CLKAM_ENABLE();
    __HAL_RCC_D3SRAM1_CLKAM_ENABLE();

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* MPU Configuration */

void MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct = {0};

    /* Disables the MPU */
    HAL_MPU_Disable();

    /** Initializes and configures the Region and the memory to be protected
    */
    MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER0;
    MPU_InitStruct.BaseAddress = 0x30040000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
    MPU_InitStruct.SubRegionDisable = 0x0;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;//  MPU_ACCESS_SHAREABLE
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    /** Initializes and configures the Region and the memory to be protected
    */
    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    MPU_InitStruct.BaseAddress = 0x30044000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    /* Enables the MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */
    __disable_irq();
    while (1)
    {
    }
    /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Lwip.c 中修改ethernet_link_status_updated函数

static void ethernet_link_status_updated(struct netif *netif)//网络连接状态更新
{
    printf("\r\n enter netif_status_updated func\r\n");
    HAL_Delay(500);
    if (netif_is_up(netif))
    {
        printf("link available\r\n");
        printf("IP:%hhu.%hhu.%hhu.%hhu\r\n", ip4_addr1_val(netif->ip_addr), ip4_addr2_val(netif->ip_addr),
               ip4_addr3_val(netif->ip_addr), ip4_addr4_val(netif->ip_addr));
        printf("NM:%hhu.%hhu.%hhu.%hhu\r\n", ip4_addr1_val(netif->netmask), ip4_addr2_val(netif->netmask),
               ip4_addr3_val(netif->netmask), ip4_addr4_val(netif->netmask));
        printf("GW:%hhu.%hhu.%hhu.%hhu\r\n", ip4_addr1_val(netif->gw), ip4_addr2_val(netif->gw),
               ip4_addr3_val(netif->gw), ip4_addr4_val(netif->gw));
        /* USER CODE BEGIN 5 */
        /* USER CODE END 5 */
    }
    else /* netif is down */
    {
        /* USER CODE BEGIN 6 */
        printf("link unavailable\r\n");
        HAL_Delay(500);

        /* USER CODE END 6 */
    }
}

作者:zztxr-c

物联沃分享整理
物联沃-IOTWORD物联网 » STM32H7单片机通过STM32CUBEMX移植LWIP,DHCP+tcp_client与上位机通信以及网线断开重连和tcp客户端断开重连机制,通信速率测试能到34Mbps

发表回复