GD32F407之LWIP的移植和UDP_TCPC测试

本文详细介绍了如何在STM32F407上移植LWIP网络栈,并通过UDP和TCP通信进行验证。首先,讲述了LWIP的移植步骤,包括内核文件移植、arch文件添加、通用文件夹配置以及LWIP的剪裁和配置。接着,讨论了UDP接口编程,包括LWIP UDP协议函数及其回调机制,并给出了UDP客户端数据传输的示例。最后,简要探讨了TCP接口编程,展示了TCP服务端数据传输的实现。
摘要由CSDN通过智能技术生成

一、LWIP的移植

1Lwip内核文件的移植参考正点原子的STM32F407无操作系统的移植,如图工程文件目录结构

2、添加arch文件

由于不使用RTOS实时系统所以,(cc.h、cpu.h、perf.h、sys_arch.h、sys_arch.c)基本不使用,所以也没有正点原子里面的Lwip_Arch文件夹,只是简单地实现了获取时间函数sys_now();代码在lwip_comm.c中。

3、添加LWIP通用文件

Lwip_App为通用文件夹,里面包含五个文件夹lwip_comm (lwip_comm.c、lwip_comm.h是LWIP源码和前面的以太网驱动库结合起来的桥梁。lwipopts.h是用来剪裁和配置LWIP的文件)、tcp_client_demo、tcp_server_demo、udp_demo、web_server_demo,后面这四个是网络应用的功能函数,lwip_comm.h里面定义了本机MAC地址,远端主机IP地址,本机IP地址,子网掩码,默认网关和是否使用DHCP

4、LWIP的剪裁和配置

在LWIP的源码中有一个opt.h的文件,这个文件就是剪裁和配置LWIP的,不过最好不要在这个文件里面修改,我们可以在其他的文件中定义来覆盖opt.h里面的定义,所以前面提过的LWIP->Lwip_App->Lwip_comm里面的lwipopt.h就是重新定义来剪裁配置LWIP的

到这简单LWIP移植就OK了(详细参考正点原子),为了验证是否有效下面我们做UDP和TCP通信来验证

二、UDP接口编程

对于UDP的协议可以网上参考,主要说明一下LWIP中的UDP协议函数(参考正点原子STM32F407LWIP开发手册)在LWIP的源码中有udp.c和udp.h两个和UDP有关的函数(lwip-1.4.1\src\core)

Udp.c中与UDP报文处理有关的函数之间关系图

Lwip的RAW_API编程方式是基于回调机制的,当我们初始化应用的时候我们必须为内核中的不同事件注册相应的回调函数,当事件发生的时候这些回调函数就会被调用,部分函数说明

我们简单做一个demo来测试UPD客户端数据传输功能

#define UDP_DEMO_PORT 8090     //本地端口

uint8_t udp_demo_recvbuf[100]; //UDP接收数据缓冲区 
uint8_t udp_demo_sendbuf[50];  //UDP发送数据内容缓冲区 
uint8_t UdpRecelen=0;
/******************************************************************************
* 描述  : 创建udp客户端
* 参数  : 无
* 返回  : 无
******************************************************************************/
void udp_echo_init(void)
{
    struct udp_pcb *udp_client_pcb;  
  
    /* 为udp客户端分配一个udp_pcb结构体 */
    udp_client_pcb = udp_new();
	
    /* 绑定本地端号和IP地址 */
    udp_bind(udp_client_pcb, IP_ADDR_ANY, UDP_DEMO_PORT); 
	
    /* 注册接收回调函数 */
    udp_recv(udp_client_pcb,udp_demo_recv,NULL);
}
 /******************************************************************************
 * 描述  : 接收回调函数
 * 参数  : -
 * 返回  : 无
 ******************************************************************************/
void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p,struct ip_addr *addr,u16_t port)
{
    uint32_t data_len = 0;
    struct pbuf *q;
	
    if(p!=NULL){	
        memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE); 
		
	/* 遍历整个pbuf链表 */
	for(q=p;q!=NULL;q=q->next){
	    //判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于
            //UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于
	    //的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
	    if(q->len > (UDP_DEMO_RX_BUFSIZE-data_len)){
                memcpy(udp_demo_recvbuf+data_len,q->payload,(UDP_DEMO_RX_BUFSIZE- data_len));
            }            
	    else memcpy(udp_demo_recvbuf+data_len,q->payload,q->len);
	    
            data_len += q->len;  	
	    if(data_len > UDP_DEMO_RX_BUFSIZE) break; 
        }
	/* 接收的数据长度 */
	UdpRecelen = data_len;
		
	/* 记录远端主机的IP地址 */
	upcb->remote_ip=*addr; 		
	/* 记录远端主机的端口号 */
	upcb->remote_port=port;  		

	/* 接收数据处理函数 */
	UDP_ReceData_Handler(upcb,UdpRecelen);
		
	/* 释放缓冲区数据 */
	pbuf_free(p);
    } 
} 
/******************************************************************************
* 描述  : 发送udp数据
* 参数  : 
* 返回  : 无
******************************************************************************/
void udp_demo_senddata(struct udp_pcb *upcb,uint8_t *sendbuf)
{
    struct pbuf *ptr;
	
    /* 分配缓冲区空间 */
    ptr=pbuf_alloc(PBUF_TRANSPORT,strlen((char*)sendbuf),PBUF_POOL); 
	
    if(ptr){
	/* 填充缓冲区数据 */
	ptr->payload=(void*)sendbuf;
		
	/* 发送udp数据 */
	udp_send(upcb,ptr);
		
	/* 释放缓冲区空间 */
	pbuf_free(ptr);
    }
}
/******************************************************************************
* 描述  : udp数据处理函数
* 参数  : 
* 返回  : 无
******************************************************************************/

void UDP_ReceData_Handler(upcb,UdpRecelen)
{
    /* 将接收到的数据再转发出去 */
    udp_demo_senddata(upcb,udp_demo_recvbuf);
	
    /* 也可以做一些判断,在做自己的功能 */
    /* 发送 0x2a 0x01 数据*/
    if(UdpRecelen>=2){
        if((0x01 == udp_demo_recvbuf[1]) && (0x2a==udp_demo_recvbuf[0])){
	    //Read BMC version
	    printf("Hello LWIP UDP demo");
	}
	memset(udp_demo_sendbuf,0,UDP_DEMO_RX_BUFSIZE);
	UdpRecelen = 0;
    }else{
        UdpRecelen = 0 ;
    }
}

三、TCP接口编程

对于TCP的协议可以网上参考,主要说明一下LWIP中的TCP协议函数(参考正点原子STM32F407LWIP开发手册)

在LWIP的源码中有tcp.c,tcp.h,tcp_in.c和tcp_out.c函数和TCP有关(lwip-1.4.1\src\core)

TCP层中函数关系图:

LWIP提供的TCP函数,

我们简单做一个demo来测试TCP服务端数据传输功能

/******************************************************************************
* 描述  : 创建tcp服务器
* 参数  : 无
* 返回  : 无
******************************************************************************/
void Tcp_Server_Init(void)
{
    struct tcp_pcb *tcp_server_pcb;

    /* 为tcp服务器分配一个tcp_pcb结构体    */
    tcp_server_pcb = tcp_new();

    /* 绑定本地端号和IP地址 */
    tcp_bind(tcp_server_pcb, IP_ADDR_ANY, 80);

    /* 监听之前创建的结构体tcp_server_pcb */
    tcp_server_pcb = tcp_listen(tcp_server_pcb);

    /* 初始化结构体接收回调函数 */
    tcp_accept(tcp_server_pcb, tcp_server_accept);
}
/******************************************************************************
* 描述  : 客户端接入回调函数
* 参数  : -
* 返回  : -
******************************************************************************/
static err_t tcp_server_accept(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  "), 1);

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

    return ERR_OK;
}

/******************************************************************************
* 描述  : 接收回调函数
* 参数  : -
* 返回  : -
******************************************************************************/
static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *tcp_recv_pbuf, err_t err)
{
    struct pbuf *tcp_send_pbuf;
    struct name *name = (struct name *)arg;

    if (tcp_recv_pbuf != NULL)
    {
        /* 扩大收发数据的窗口 */
        tcp_recved(pcb, tcp_recv_pbuf->tot_len);

        if (!name)
        {
            pbuf_free(tcp_recv_pbuf);
            return ERR_ARG;
        }

        /* 将接收的数据拷贝给发送结构体 */
        tcp_send_pbuf = tcp_recv_pbuf;

        /* 换行 */
        tcp_write(pcb, "\r\n", strlen("\r\n"), 1);
        /* 将接收到的数据再转发出去 */
        tcp_write(pcb, tcp_send_pbuf->payload, tcp_send_pbuf->len, 1);

        pbuf_free(tcp_recv_pbuf);
    }
    else if (err == ERR_OK)
    {
        /* 释放内存 */
        mem_free(name);
        return tcp_close(pcb);
    }

    return ERR_OK;
}

这里只是简单的介绍了一下LWIP的UDP和TCP,对于整个LWIP还是非常的复杂,如果想继续深入了解LWIP可以翻看LWIP的源码---http://download.savannah.gnu.org/releases/lwip/

 

### 回答1: gd32f450是一款基于ARM Cortex-M4内核的微控制器系列,它集成了lwIP(轻量级IP)协议栈。lwIP是一个用于嵌入式系统的开源TCP/IP协议栈,它具有轻量级、模块化和可裁剪的特点,适用于资源受限的嵌入式设备。 gd32f450 lwip的集成,在嵌入式系统中提供了方便的网络通信功能。通过gd32f450系列微控制器的lwip协议栈,可以实现TCP/IP网络通信,包括IP地址分配、IP数据包传输、网络连接、Socket编程等。lwIP协议栈还支持常见的网络协议,如UDP、ARP、ICMP等,能够满足基本的网络通信需求。 使用gd32f450 lwip的好处是,它提供了一种简单、高效的网络通信解决方案。通过lwIP协议栈,开发人员可以轻松地在gd32f450微控制器上实现网络通信功能,而无需编写底层的网络协议代码。这将大大加速开发过程,同时降低了开发成本。 此外,gd32f450系列微控制器具有丰富的外设资源,包括多个串行通信接口(如UART、I2C、SPI)、多个定时器和计数器、以太网MAC控制器等。这为网络通信提供了更多的选择和灵活性。gd32f450 lwip的集成,使得开发人员可以更加方便地利用这些外设,快速构建网络应用。 总而言之,gd32f450 lwip是一种强大的网络通信解决方案,它集成了lwIP协议栈,为嵌入式系统提供了简单、高效的网络通信功能。通过gd32f450 lwip,开发人员可以轻松地实现TCP/IP网络通信,加速开发过程,降低开发成本。 ### 回答2: gd32f450 lwip是一种基于GD32F450系列微控制器的轻量级IP(Internet Protocol)网络协议栈。该协议栈可以与硬件平台进行结合,用于实现网络通信功能。lwip是一个开源的协议栈,它提供了TCP/IP协议以及其他网络协议的支持,可以方便地在嵌入式系统中实现网络通信。 gd32f450 lwip的主要特点是轻巧、高效、可靠。它具有占用资源少的特点,适用于资源有限的嵌入式系统。同时,它提供了高度可定制和可移植的特性,可以根据具体需求进行配置和移植gd32f450 lwip可以支持多个网络接口,包括以太网和Wi-Fi接口,可以实现网络连接和数据传输。 gd32f450 lwip提供了丰富的API接口,使得开发人员可以方便地进行网络编程。它支持多个应用层协议,包括HTTP、FTP、SNMP等,可以用于实现各种网络应用。 总之,gd32f450 lwip是一种适用于嵌入式系统的网络协议栈,能够方便地实现网络通信功能。它具有轻巧、高效、可靠的特点,并提供了丰富的API接口和应用层协议支持。它的优点和灵活性使得它成为嵌入式系统中网络通信的理想选择。 ### 回答3: gd32f450是一款微控制器芯片,它采用了lwip协议栈。lwip(Lightweight IP)是一个轻量级的网络协议栈,专为嵌入式系统设计。gd32f450芯片集成了lwip协议栈,使其可以在嵌入式系统中实现网络通信。 gd32f450 lwip提供了一系列的网络协议,包括IP协议、TCP协议和UDP协议等。它可以通过以太网接口连接到网络,支持数据的传输和接收。使用lwip协议栈,gd32f450可以实现TCP/IP通信,并支持基于IP地址的网络连接。 gd32f450 lwip还具有高度的灵活性和可扩展性,可以根据需要进行配置和定制。它支持多种网络通信协议,包括SNMP和DHCP等。gd32f450 lwip还提供了API接口,方便用户进行相关功能的开发和调试。 总之,gd32f450 lwip是一款功能强大的微控制器芯片,它集成了lwip协议栈,可以实现网络通信功能。它的高度灵活性和可扩展性使得它适用于各种嵌入式系统应用场景,如物联网设备、无线通信设备和工业自动化控制等。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值