你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32F769I-DISC1】LWIP手工移植

[复制链接]
lugl 发布时间:2025-2-25 14:10

【前言】

前段时间参与加论坛的【GUI Demo】活动,有幸的得到了STM32F769I-DISC1开发板。收到开发板后,才发现没有给适配屏幕。由于开发板的接口是DSI接口的屏幕,手上只有STM32U599的屏的接口可以,但是屏与开发板的上REST键有冲突,键比较高,唯一能对上的屏也用不了。所以以能先把屏放一边,先把网络给对接上。

【项目规划】

我申请的项目是使用RTT连上deepseek服务器,进行AI对话。到RTT官网上查看了一下,STM32F769DISC是还没有适配的。所以先使用FreeRTOS进行LWIP适配,然后通过TCP与服务器进行交互。现在先做规划如下:

1、移植shell工具,由于先不使用RTT,所以需要先移植一个shell进行交互。

2、移植freeRTOS,只有在RTOS的支持下,才能更好的协调开发板做更多的事。

3、移植LWIP,通过LWIP才能与服务器进行交互。

4、创建TCP—CLIENT测试与服务器的交互。

5、配置本地的deepseek服务。使用网页提交与开发板建立通信。

6、适配屏幕用于交互结果的展示。、

整个荐

【项目搭建软件配置】

1、STM32CubeMX,用于基础CMake工程的创建。

2、Vscode,用于代码的编写,下载、调试。

3、用于支持工程的各种vscode插件,主要有CMakeTOOLS、STM32 VS Code Extension等。

【移植过程】

一、使用stm32CubeMX创建基础工程,选择STM32F768nihxMCU,开启USART1、LED等基础外设,同时配置FreeRTOS,使用TIM6作为SYS的心跳定时器。

创建好后,选择为Cmake工程。

二、使用vscode打开工程,由CmakeLists.txt自动配置好工程,并且使用USART1在串口输出字符。

三、移植nr_micro_shell,nr_micro_shell是一款开源的shell工具,占用内存与闪存小,容量移植。

1、首先下载源码https://gitee.com/nrush/nr_micro_shell

2、把源代码添加进工程的ThirdPart目录下面,编写分块的CmakeLists.txt。将src下所有的.c都添加进工程,同时把inc文件目录添加进工程中。

3、修改nr_micro_shell_conf.h中的参数,我使用MobXterm工具进行交互,所以回车选择为1,即\r。

/*
0: \n
1: \r
2: \r\n
*/
#define NR_SHELL_END_OF_LINE 1

4、修改shell_printf代码如下:

/* If you use RTOS, you may need to do some special processing for printf(). */
#define shell_printf(fmt, args...) printf(fmt, ##args); \
                                                         \
    fflush(stdout);
#define ansi_show_char(x) putchar(x); \
                                       \
    fflush(stdout);

#endif

5、在usart.c中引入stdio.h,添加串口重定向代码:

/* USER CODE BEGIN 1 */
#define CMD_BUFFER_SIZE 128

#ifdef __GNUC__
int _write(int fd, char *ptr, int len)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, 0xFFFF);
  return len;
}

#endif
/* USER CODE END 1 */

通过printf来测试一下,是否能正常输出。

6、创建用户代码来对接shell,usart_shell.c,主要是添加中断接收函数,实现对串口数据的接收,同时创建几个shell cmd,比如LED灯的控制等,代码如下:

/******************************************************************************
 * Include files
 ******************************************************************************/
#include "shell_uart.h"
#include <stdio.h>

static uint8_t  uart_recv_buff[4];

shell_uart_buffer_t  g_shell_uart=
{
    .tx.read_i = 0,
    .tx.write_i = 0,

    .rx.read_i = 0,
    .rx.write_i = 0,

    .tx_cpl = 0,
};


//////////////////////////////////////////////////////////////////////////////
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)   //shell
    {
        if(((g_shell_uart.rx.write_i+1)&0x1ff) != g_shell_uart.rx.read_i)
        {
            g_shell_uart.rx.buff[g_shell_uart.rx.write_i++] = uart_recv_buff[0] & 0xff;
            g_shell_uart.rx.write_i &= 0x1ff;//256Byte
        }
        HAL_UART_Receive_IT(huart,uart_recv_buff,1);//
    }
}


//
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)   //shell
    {
        HAL_UART_Receive_IT(huart,uart_recv_buff,1);//
    }
}





void shell_usart_init(void)
{
#ifdef UART_SHELL
#if UART_SHELL == 1
    userShellInit(); //LETTER_SHELL
#elif UART_SHELL == 2
    shell_init();   //NR_MICRO_SHELL
#endif
#endif
    HAL_UART_Receive_IT(&huart1,uart_recv_buff,1);//
}

#include "string.h"
#include "ctype.h"

static void list_cmd(void)
{
    unsigned int i = 0;
    for (i = 0; nr_shell.static_cmd[i].fp != NULL; i++)
    {
        shell_printf("%s\t\t", nr_shell.static_cmd[i].cmd);
        if (nr_shell.static_cmd[i].description != NULL)
            shell_printf("\"%s\"\t\t", nr_shell.static_cmd[i].description);
        shell_printf("\r\n");
    }
}
/**
 * @brief ls command
 */
void shell_ls_cmd(char argc, char *argv)
{
    if (argc > 1)
    {
        if (!strcmp("cmd", &argv[argv[1]]))
        {
            list_cmd();
        }
        else if (!strcmp("-v", &argv[argv[1]]))
        {
            shell_printf("ls version 1.0.\r\n");
        }
        else // if (!strcmp("-h", &argv[argv[1]]))
        {
            goto exit_lable;
        }
        return;
    }
    shell_printf("ls need more arguments!\r\n\r\n");

exit_lable:
    shell_printf("useage: ls [options]\r\n");
    shell_printf("options: \r\n");
    shell_printf("\t -h \t: show help\r\n");
    shell_printf("\t -v \t: show version\r\n");
    shell_printf("\t cmd \t: show all commands\r\n");
}

void shell_help_cmd(char argc, char *argv)
{
    list_cmd();
}

/**
 * @brief test command
 */
void shell_test_cmd(char argc, char *argv)
{
    unsigned int i;
    shell_printf("test command:\r\n");
    for (i = 0; i < argc; i++)
    {
        shell_printf("paras %d: %s\r\n", i, &(argv[argv[i]]));
    }
}

/* LED shell LED*/

void shell_led_cmd(char argc, char *argv)
{
    if(argc ==  2)
    {
        if(!strcmp("LED", &argv[argv[0]]) )
        {
            if(!strcmp("on", &argv[argv[1]]))
            {
                HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);
                shell_printf("LED on\r\n");
            }
            else if(!strcmp("off", &argv[argv[1]]))
            {
                HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET);
                shell_printf("LED off\r\n");
            }
            else
            {
                shell_printf("ERRO CMD:led %s\r\n", &argv[1]);
            }
        }
        else
        {
            shell_printf("ERRO CMD:led %s\r\n", &argv[0]);
        }
    }
}
#ifdef NR_SHELL_USING_EXPORT_CMD
NR_SHELL_CMD_EXPORT(help, shell_help_cmd, "help");
NR_SHELL_CMD_EXPORT(ls, shell_ls_cmd, "list cmd");
NR_SHELL_CMD_EXPORT(test, shell_test_cmd, "test cmd");

#else
const static_cmd_st static_cmd[] =
    {
        {"help", shell_help_cmd, "list cmd"},
        {"ls", shell_ls_cmd, "list cmd"},
        {"test", shell_test_cmd, "test cmd"},
        {"LED", shell_led_cmd, "LED on/off"},
        {"\0", NULL}
    };

#endif
void shell_usart_loop(void)
{
    if(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
    {
        shell(g_shell_uart.rx.buff[g_shell_uart.rx.read_i++]);
        g_shell_uart.rx.read_i &= 0x1ff; //256Byte
    }

}

在主程中使用shell_usart_init();启动shell,并在任务中使用shell_usart_loop();为周期调用shell。

下载到开发板后,可以实现与开发的交互:

▒
nr@root:
nr@root:
nr@root:ls
ls need more arguments!

useage: ls [options]
options:
         -h     : show help
         -v     : show version
         cmd    : show all commands
nr@root:LED on
LED on
nr@root:

四、移植Lwip

STM32F769板载了网络接口,这就可以实现联网。由于没有基于stm32cubeMX的示例,我通过配置ETH以及LWIP但是没有成功的获取IP,所以手工进行移植。

【前期准备】

1、在官方的示例中,有基于MDK的联网示例,我是基于vscode的工程,所以只能做为学习的示例。

2、在github上面找到了一个基于stm32cubIDE的联网工程,能联上网,但是他是基于mqtt还有http的,他的工程是基于LCD的,所以我也只能拿过来学习。

3、然后我还使用stm32cubeMX配置了FreeRTOS。

在这样的前提下,我进行如下的方法,成功的实现了LWIP联网。

【源码的移植】

1、我将STM32CubeIDE的工程中的lwip源码,复制到我工程目录ThirdPart下面

image.png

2、然后根据Filielists.mk编把工程中的文件夹以及.c添加进CMakeLists.txt中。

image.png

最后添加好后文件如下:


add_library(ThirdPart INTERFACE)

target_include_directories(ThirdPart INTERFACE
    ./nr_micro_shell/inc

    ./lwip/src/include
    ./lwip/src/include/lwip
    ./lwip/src/include/lwip/apps
    ./lwip/src/include/lwip/priv
    ./lwip/src/include/lwip/prot
    ./lwip/src/include/netif
    ./lwip/src/include/posix
    ./lwip/src/include/posix/sys
    ./lwip/system  
    ./lwip/LwIP/system
    ./lwip/src/include/netif/ppp

)

target_sources(ThirdPart INTERFACE
    ./nr_micro_shell/src/ansi_port.c
    ./nr_micro_shell/src/nr_micro_shell.c
    ./nr_micro_shell/src/ansi.c

    ./lwip/src/core/init.c
    ./lwip/src/core/def.c 
    ./lwip/src/core/dns.c 
    ./lwip/src/core/inet_chksum.c 
    ./lwip/src/core/ip.c 
    ./lwip/src/core/mem.c 
    ./lwip/src/core/memp.c 
    ./lwip/src/core/netif.c 
    ./lwip/src/core/pbuf.c 
    ./lwip/src/core/raw.c 
    ./lwip/src/core/stats.c 
    ./lwip/src/core/sys.c 
    ./lwip/src/core/tcp.c 
    ./lwip/src/core/tcp_in.c 
    ./lwip/src/core/tcp_out.c 
    ./lwip/src/core/timeouts.c 
    ./lwip/src/core/udp.c
    ./lwip/src/core/ipv4/autoip.c 
    ./lwip/src/core/ipv4/dhcp.c 
    ./lwip/src/core/ipv4/etharp.c 
    ./lwip/src/core/ipv4/icmp.c 
    ./lwip/src/core/ipv4/igmp.c 
    ./lwip/src/core/ipv4/ip4_frag.c 
    ./lwip/src/core/ipv4/ip4.c 
    ./lwip/src/core/ipv4/ip4_addr.c
    ./lwip/src/api/api_lib.c 
    ./lwip/src/api/api_msg.c 
    ./lwip/src/api/err.c 
    ./lwip/src/api/netbuf.c 
    ./lwip/src/api/netdb.c 
    ./lwip/src/api/netifapi.c 
    ./lwip/src/api/sockets.c 
    ./lwip/src/api/tcpip.c
    ./lwip/src/netif/ethernet.c
    ./lwip/src/netif/slipif.c
    ./lwip/src/netif/ppp/auth.c 
    ./lwip/src/netif/ppp/ccp.c 
    ./lwip/src/netif/ppp/chap-md5.c 
    ./lwip/src/netif/ppp/chap_ms.c 
    ./lwip/src/netif/ppp/chap-new.c 
    ./lwip/src/netif/ppp/demand.c 
    ./lwip/src/netif/ppp/eap.c 
    ./lwip/src/netif/ppp/ecp.c 
    ./lwip/src/netif/ppp/eui64.c 
    ./lwip/src/netif/ppp/fsm.c 
    ./lwip/src/netif/ppp/ipcp.c 
    ./lwip/src/netif/ppp/ipv6cp.c 
    ./lwip/src/netif/ppp/lcp.c 
    ./lwip/src/netif/ppp/magic.c 
    ./lwip/src/netif/ppp/mppe.c 
    ./lwip/src/netif/ppp/multilink.c 
    ./lwip/src/netif/ppp/ppp.c 
    ./lwip/src/netif/ppp/pppapi.c 
    ./lwip/src/netif/ppp/pppcrypt.c 
    ./lwip/src/netif/ppp/pppoe.c 
    ./lwip/src/netif/ppp/pppol2tp.c 
    ./lwip/src/netif/ppp/pppos.c 
    ./lwip/src/netif/ppp/upap.c 
    ./lwip/src/netif/ppp/utils.c 
    ./lwip/src/netif/ppp/vj.c 
    ./lwip/src/netif/ppp/polarssl/arc4.c 
    ./lwip/src/netif/ppp/polarssl/des.c 
    ./lwip/src/netif/ppp/polarssl/md4.c 
    ./lwip/src/netif/ppp/polarssl/md5.c 
    ./lwip/src/netif/ppp/polarssl/sha1.c

    ./lwip/src/apps/snmp/snmp_asn1.c 
    ./lwip/src/apps/snmp/snmp_core.c 
    ./lwip/src/apps/snmp/snmp_mib2.c 
    ./lwip/src/apps/snmp/snmp_mib2_icmp.c 
    ./lwip/src/apps/snmp/snmp_mib2_interfaces.c 
    ./lwip/src/apps/snmp/snmp_mib2_ip.c 
    ./lwip/src/apps/snmp/snmp_mib2_snmp.c 
    ./lwip/src/apps/snmp/snmp_mib2_system.c 
    ./lwip/src/apps/snmp/snmp_mib2_tcp.c 
    ./lwip/src/apps/snmp/snmp_mib2_udp.c 
    ./lwip/src/apps/snmp/snmp_msg.c 
    ./lwip/src/apps/snmp/snmpv3.c 
    ./lwip/src/apps/snmp/snmp_netconn.c 
    ./lwip/src/apps/snmp/snmp_pbuf_stream.c 
    ./lwip/src/apps/snmp/snmp_raw.c 
    ./lwip/src/apps/snmp/snmp_scalar.c 
    ./lwip/src/apps/snmp/snmp_table.c 
    ./lwip/src/apps/snmp/snmp_threadsync.c 
    ./lwip/src/apps/snmp/snmp_traps.c 
    ./lwip/src/apps/snmp/snmpv3_mbedtls.c 
    ./lwip/src/apps/snmp/snmpv3_dummy.c
    # ./lwip/src/apps/httpd/fs.c 
    # ./lwip/src/apps/httpd/httpd.c
    ./lwip/src/apps/sntp/sntp.c

    ./lwip/src/apps/netbiosns/netbiosns.c
    ./lwip/src/apps/tftp/tftp_server.c
    ./lwip/src/apps/mqtt/mqtt.c
    ./lwip/system/OS/sys_arch.c
)

# target_link_directories(ThirdPart INTERFACE
# )

# target_link_libraries(ThirdPart INTERFACE
# )

2、复制示例中的ethernetif.c/h、app_ethernet.c到工程中。

3、在stm32f7xx_it.c中添加中断回调函数:

/* USER CODE BEGIN 1 */
void ETH_IRQHandler(void)
{
  HAL_ETH_IRQHandler(&EthHandle);
}
/* USER CODE END 1 */
image.png
image.png
收藏 评论5 发布时间:2025-2-25 14:10

举报

5个回答
lugl 回答时间:前天 14:26

【由于最长只支持这么多字,所以另起】

4、由于是手工添加ETH的驱动,所以需要在stm32f7xx_hal_conf.h中打开ETH的配置

image.png

同时添加网络参数:

/* ################## Ethernet peripheral configuration ##################### */

/* Section 1 : Ethernet peripheral configuration */

/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#define MAC_ADDR0   2U
#define MAC_ADDR1   0U
#define MAC_ADDR2   0U
#define MAC_ADDR3   0U
#define MAC_ADDR4   0U
#define MAC_ADDR5   0U

/* Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE                ETH_MAX_PACKET_SIZE /* buffer size for receive               */
#define ETH_TX_BUF_SIZE                ETH_MAX_PACKET_SIZE /* buffer size for transmit              */
#define ETH_RXBUFNB                    ((uint32_t)4U)       /* 4 Rx buffers of size ETH_RX_BUF_SIZE  */
#define ETH_TXBUFNB                    ((uint32_t)4U)       /* 4 Tx buffers of size ETH_TX_BUF_SIZE  */

/* Section 2: PHY configuration section */
 /* LAN8742A PHY Address*/
#define LAN8742A_PHY_ADDRESS 0x00U
 /* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS
 /* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
 /* PHY Configuration delay */
#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)

#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)

   /* Section 3: Common PHY Registers */

#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register   */
#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register    */

#define PHY_RESET ((uint16_t)0x8000U)                   /*!< PHY Reset */
#define PHY_LOOPBACK ((uint16_t)0x4000U)                /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U)         /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U)         /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U)          /*!< Set the full-duplex mode at 10 Mb/s  */
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U)          /*!< Set the half-duplex mode at 10 Mb/s  */
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U)         /*!< Enable auto-negotiation function     */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function    */
#define PHY_POWERDOWN ((uint16_t)0x0800U)               /*!< Select the power down mode           */
#define PHY_ISOLATE ((uint16_t)0x0400U)                 /*!< Isolate PHY from MII                 */

#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed   */
#define PHY_LINKED_STATUS ((uint16_t)0x0004U)     /*!< Valid link established               */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002U)  /*!< Jabber condition detected            */

 /* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)0x1FU) /*!< PHY special control/ status register Offset     */

#define PHY_SPEED_STATUS ((uint16_t)0x0004U)  /*!< PHY Speed mask                                  */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0010U) /*!< PHY Duplex mask                                 */

#define PHY_ISFR ((uint16_t)0x1DU)        /*!< PHY Interrupt Source Flag register Offset       */
#define PHY_ISFR_INT4 ((uint16_t)0x0010U) /*!< PHY Link down inturrupt                         */
lugl 回答时间:前天 14:28

5、在main.h中添加用户IP地址的配置参数,主要是配置是否启用DHPCP,配置静态IP的地址、DNS、网关参数:

/* USER CODE BEGIN ET */
#define USE_DHCP /* enable DHCP, if disabled static address is used*/

/*Static IP ADDRESS*/
#define IP_ADDR0 192
#define IP_ADDR1 168
#define IP_ADDR2 3
#define IP_ADDR3 236

/*NETMASK*/
#define NETMASK_ADDR0 255
#define NETMASK_ADDR1 255
#define NETMASK_ADDR2 255
#define NETMASK_ADDR3 0

/*Gateway Address*/
#define GW_ADDR0 192
#define GW_ADDR1 168
#define GW_ADDR2 3
#define GW_ADDR3 1
  /* USER CODE END ET */
lugl 回答时间:前天 14:30

编写一个tcp_client.c/h,来测试与tcp_server的通信。

#include "lwip/tcp.h"
#include "lwip/netif.h"
#include "lwip/init.h"
#include "lwip/sys.h"
#include "lwip/ip_addr.h"
#include "shell_uart.h"
#include "string.h"

static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static err_t tcp_client_send(struct tcp_pcb *tpcb, const char *data, u16_t len);

    static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    if (err != ERR_OK)
    {
        tcp_close(tpcb);
        return err;
    }
    shell_printf("tcp_client connected\r\n");

    // Set the receive callback function
    tcp_recv(tpcb, tcp_client_recv);

    // Send data to the server
    const char *data = "Hello, Server!\r\n";
    tcp_client_send(tpcb, data, strlen(data));

    // Send data or perform other actions upon successful connection
    return ERR_OK;
}

static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    if (p == NULL)
    {
        tcp_close(tpcb);
        return ERR_OK;
    }
    // Process received data
    shell_printf("Received data: %.*s\n", p->tot_len, (char *)p->payload);

    // Indicate that the data has been received
    tcp_recved(tpcb, p->tot_len);

    // Free the received pbuf
    pbuf_free(p);

    // Continue to receive data
    tcp_recv(tpcb, tcp_client_recv);
    return ERR_OK;
}

static void tcp_client_error(void *arg, err_t err)
{
    // Handle error
    shell_printf("TCP error: %d\n", err);
}

static err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb)
{
    // Handle periodic actions
    return ERR_OK;
}

static err_t tcp_client_send(struct tcp_pcb *tpcb, const char *data, u16_t len)
{
    struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_POOL);
    if (p == NULL)
    {
        shell_printf("Failed to allocate pbuf\n");
        return ERR_MEM;
    }
    memcpy(p->payload, data, len);
    err_t err = tcp_write(tpcb, p->payload, len, TCP_WRITE_FLAG_COPY);
    if (err != ERR_OK)
    {
        shell_printf("Failed to send data: %d\n", err);
        pbuf_free(p);
        return err;
    }
    err = tcp_output(tpcb);
    if (err != ERR_OK)
    {
        shell_printf("Failed to output data: %d\n", err);
        pbuf_free(p);
        return err;
    }
    pbuf_free(p);
    return ERR_OK;
}

void tcp_client_init(void)
{
    struct tcp_pcb *tpcb;
    ip_addr_t server_ip;

    IP4_ADDR(&server_ip, 192, 168, 3, 231);

    tpcb = tcp_new();
    if (tpcb != NULL)
    {
        tcp_arg(tpcb, NULL);
        tcp_err(tpcb, tcp_client_error);
        tcp_poll(tpcb, tcp_client_poll, 1);
        err_t err = tcp_connect(tpcb, &server_ip, 8000, tcp_client_connected);
        if (err != ERR_OK)
        {
            shell_printf("tcp_client err: %d\r\n", err);
            tcp_close(tpcb);
        }
        else
        {
            shell_printf("tcp_client OK\r\n");
        }
    }
    else
    {
        shell_printf("Failed to create TCP PCB\n");
    }
}
lugl 回答时间:前天 14:32

6、在freertos任务中,调用lwip初始,等待网卡连接以及动态获取到IP然后连接tcp_server。

/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  tcpip_init(NULL, NULL);
  Netif_Config();
  User_notification(&gnetif);
#ifdef USE_DHCP
  /* Start DHCPClient */
  osThreadDef(DHCP, DHCP_thread, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 5);
  osThreadCreate(osThread(DHCP), &gnetif);
#endif
  // 等待网络接口启用
  while (!netif_is_up(&gnetif))
  {
    shell_printf("Waiting for network interface to be up...\n");
    osDelay(1000);
  }

  // 等待获取IP地址
  while (ip_addr_isany(netif_ip4_addr(&gnetif)))
  {
    shell_printf("Waiting for IP address...\n");
    osDelay(1000);
  }

  shell_printf("IP address obtained: %s\n", ipaddr_ntoa(netif_ip4_addr(&gnetif)));

  // 启动TCP客户端
  tcp_client_init();
  for(;;)
  {
    shell_usart_loop();
    osDelay(100);
  }
  /* USER CODE END StartDefaultTask */
}
lugl 回答时间:前天 14:34

【测试效果】

下载到开发板后,在电脑端创建一个TCP_SERVER,然后打shell,从server发送数据,就可以在shell中打印出tcp接收到的数据了。

image.png

到此,移植Lwip就完成了。也成功的实现了数据的交互。

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版