IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F107+LAN8720A使用STM32cubeMX配置网络连接+tcp主从机+UDP app -> 正文阅读

[嵌入式]STM32F107+LAN8720A使用STM32cubeMX配置网络连接+tcp主从机+UDP app

里面提到的资源和写完的例程放出来,后续我会放到百度云里

https://download.csdn.net/download/qq_27620407/85443546

1、CubeMX配置

在这里插入图片描述
ETH 选择RMII模式
PHY Address设置 0
RX Mode:Polling Mode
在这里插入图片描述
在这里插入图片描述
使用的不是官方芯片的话就设置 user PHY
自己命个名,无所谓是啥
下面Extened是抄的别人的,不知道啥意思
在这里插入图片描述
打开中断
在这里插入图片描述
使能LWIP 版本应该默认是最新的
关闭 TCP_QUEUE_OOSEQ

2、验证

当生成模版后,给ethernetif.c中的 HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle) 中添加LAN8720A的使能代码,然后在主函数的死循环中添加 MX_LWIP_Process()函数就可以实现在电脑上ping通STM32了

MX_LWIP_Process一定要加!!!
在这里插入图片描述

  /* USER CODE BEGIN ETH_MspInit 1 */
  //使能LAN8720A
  HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_RESET);
  HAL_Delay(50);
  HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_SET);
  /* USER CODE END ETH_MspInit 1 */
  while (1)
  {
    /* USER CODE END WHILE */

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

3、让网络连接更实用

都有注释,看看和生成的程序里不一样的地方就行,
主要就是完成等待DHCP获取IP地址并打印出来

int main(void)
{
  /* USER CODE BEGIN 1 */
static	uint8_t DHCP_Dait_Time=0,DHCP_Dait_Time_MAX=20;    //获取DHCP IP重试
	
struct netif gnetif;   //用于记录DHCP IP信息
  /* 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_DMA_Init();
  MX_TIM6_Init();
  MX_USART1_UART_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */
  //这里是一些定时器和串口配置
  HAL_TIM_Base_Start(&htim6);              //开定时器使能
  __HAL_TIM_ENABLE_IT(&htim6,TIM_IT_UPDATE);//允许更新中断
  __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能idle串口空闲中断
  HAL_UART_Receive_DMA(&huart1, USART1_DMA_RBUFF, USART1_DMA_RBUFF_LENTH);  //链接串口接收DMA
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  printf("F107_ETH_LAN8720A %s %s\r\n",__DATE__,__TIME__);
  //检查是否接上网线
	printf("lwIP Initing...\r\n");
	while(Netif_Init_Flag==0)
	{
		printf("lwIP Init failed!\r\n");
		MX_LWIP_Init();
		HAL_Delay(1200); 
		printf("Retrying...\r\n");  
	}
	printf("lwIP Inited\r\n");
	//等待DHCP获取
wait_DHCP:
  printf("等待DHCP分配\r\n");
  if(gnetif.ip_addr.addr!=0)						//正确获取到IP地址的时候
	  {
		  printf("网卡en的MAC地址为:................%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\r\n",gnetif.hwaddr[0],gnetif.hwaddr[1],gnetif.hwaddr[2],gnetif.hwaddr[3],gnetif.hwaddr[4],gnetif.hwaddr[5]);
		//解析出通过DHCP获取到的IP地址
		lwipdev.ip[3]=(uint8_t)(gnetif.ip_addr.addr>>24); 
		lwipdev.ip[2]=(uint8_t)(gnetif.ip_addr.addr>>16);
		lwipdev.ip[1]=(uint8_t)(gnetif.ip_addr.addr>>8);
		lwipdev.ip[0]=(uint8_t)(gnetif.ip_addr.addr);
		printf("通过DHCP获取到IP地址..............%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
		//解析通过DHCP获取到的子网掩码地址
		lwipdev.netmask[3]=(uint8_t)(gnetif.netmask.addr>>24);
		lwipdev.netmask[2]=(uint8_t)(gnetif.netmask.addr>>16);
		lwipdev.netmask[1]=(uint8_t)(gnetif.netmask.addr>>8);
		lwipdev.netmask[0]=(uint8_t)(gnetif.netmask.addr);
		printf("通过DHCP获取到子网掩码............%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
		//解析出通过DHCP获取到的默认网关
		lwipdev.gateway[3]=(uint8_t)(gnetif.gw.addr>>24);
		lwipdev.gateway[2]=(uint8_t)(gnetif.gw.addr>>16);
		lwipdev.gateway[1]=(uint8_t)(gnetif.gw.addr>>8);
		lwipdev.gateway[0]=(uint8_t)(gnetif.gw.addr);
		printf("通过DHCP获取到的默认网关..........%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
	  }else{
		  DHCP_Dait_Time++;
		  if(DHCP_Dait_Time<DHCP_Dait_Time_MAX)   //没有超过重试次数
		  {
			  MX_LWIP_Process();
			  HAL_Delay(500);
			  goto wait_DHCP;
		  }else{
			 printf("DHCP 获取IP失败\r\n"); 
		  }
	  }
	//
  while (1)
  {
    /* USER CODE END WHILE */

4、app

这里server、Client和UDP是在官方基础上和原子例程中改的
https://www.stmcu.com.cn/design_resource/
搜索TCP 选择 STM32 MCU
在这里插入图片描述
STSW_STM32070_LwIP_TCP_IP_STM32F4x7堆栈示例

下载后名为
STSW_STM32070_V1.1.1
STM32F4x7_ETH_LwIP_V1.1.1\Project\Standalone目录下有各种例程,都是放进工程稍微改一下变量命名就能直接用的
在这里插入图片描述
里面的

lwipopts.h文件在移植LWIP时也很有用
后续怎么移植的我不再赘述,其实就是改完编译错误后加一些自己需要的功能逻辑,目前写的也不是很完善,也够用了
以下是我改的一些app
首先是一个前置文件 LWIP_COM

LWIP_COM

.c

/**************************************
文件名:
-------------------------------------------------------------
使用说明:
------------------------------------------------------------
-------------------------------------------------------------
运行环境:
------------------------------------------------------------
版本:1.0
作者:GPY
时间:2021- -
描述:
全局变量:无
函数:内部函数:1、---;描述:
      外部函数:1、---;描述:
//------------------------------
//函数名:
//描述:
//参数:
//返回值:无
//函数调用列表:
//------------------------------
************************************/

#include "LWIP_COM.h"


uint8_t Netif_Init_Flag=0;  //自定义:标识网口是否连接成功   0连接失败  1连接成功   检查是否接上网线

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


uint32_t Remote_IP_ADDR0=192,
         Remote_IP_ADDR1=168,
         Remote_IP_ADDR2=2,
         Remote_IP_ADDR3=96;
uint16_t Remote_PORT=8089;

uint16_t UDP_Server_PORT=8081;       //UDP 服务器模式,本机监控的端口,外部的远程主机端口
uint16_t UDP_Remote_PORT=8082;       //UDP 服务器模式,本机发送的目标端口,外部的本地主机端口
uint16_t UDP_Client_PORT=8083;





.h

/**************************************
文件名:
-------------------------------------------------------------
使用说明:
------------------------------------------------------------
-------------------------------------------------------------
运行环境:
#include <stm32f10x.h>
#include "sys.h"
测试需要
#include "IO.h"
#include "USART_BASE.h"
------------------------------------------------------------
版本:1.0  
作者:
时间:2022--
描述: 
全局变量:无 
函数:
      外部函数:

************************************/
#ifndef  __LWIP_COM_H__
#define  __LWIP_COM_H__
//#include "LWIP_COM.h"
#include "User_include.h"



//lwip控制结构体
typedef struct  
{
	uint8_t mac[6];      //MAC地址
	uint8_t remoteip[4];	//远端主机IP地址 
	uint16_t remoteport;
	uint8_t ip[4];       //本机IP地址
	uint8_t netmask[4]; 	//子网掩码
	uint8_t gateway[4]; 	//默认网关的IP地址
	
	volatile uint8_t dhcpstatus;	//dhcp状态 
					//0,未获取DHCP地址;
					//1,进入DHCP获取状态
					//2,成功获取DHCP地址
					//0XFF,获取失败.
	
}__lwip_dev;

extern __lwip_dev lwipdev;						//lwip控制结构体 

extern uint32_t Remote_IP_ADDR0,
		Remote_IP_ADDR1, 
		Remote_IP_ADDR2, 
		Remote_IP_ADDR3;

extern uint16_t Remote_PORT;

extern uint16_t UDP_Remote_PORT;
extern uint16_t UDP_Server_PORT;
extern uint16_t UDP_Client_PORT;



#endif
/*-----------------file end-----------------------*/

tcp_Server

.c文件

/**
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * This file is part of and a contribution to the lwIP TCP/IP stack.
 *
 * Credits go to Adam Dunkels (and the current maintainers) of this software.
 *
 * Christiaan Simons rewrote this file to get a more stable echo example.
 *
 **/

/* This file was modified by ST */


#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include <stdio.h>
#include <string.h>

#include "tcp_echoserver.h"

//TCP Server接收数据缓冲区
uint8_t tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE];

uint8_t tcp_server_sendbuf[TCP_SERVER_RX_BUFSIZE];

uint16_t tcp_server_rec_STA=0;
//TCP Server 测试全局状态标记变量
//bit7:0,没有数据要发送;1,有数据要发送
//bit6:0,没有收到数据;1,收到数据了.
//bit5:0,没有客户端连接上;1,有客户端连接上了.
//bit4~0:保留
uint8_t tcp_server_flag;
#if LWIP_TCP


static struct tcp_pcb *tcp_echoserver_pcb;


static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err);
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_echoserver_error(void *arg, err_t err);
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb);
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es);


extern void tcp_pcb_purge(struct tcp_pcb *pcb);	//在 tcp.c里面 
extern struct tcp_pcb *tcp_active_pcbs;			//在 tcp.c里面 
extern struct tcp_pcb *tcp_tw_pcbs;				//在 tcp.c里面 
void Tcp_Sever_Cloose(void)
{
	printf("未完善,需要客户端断开才能关闭,否则还能收发数据\r\n");
	tcp_echoserver_connection_close(tcp_echoserver_pcb,0);
}
/*
TCP_Sever 发送函数  发送缓存区有上限
*/
void TCP_Server_Send(uint8_t *Data_Dend,uint32_t Len)
{
    int i=0;
    for(i=0; i<Len; i++)
    {
        tcp_server_sendbuf[i]=Data_Dend[i];
    }
    tcp_server_flag|=1<<7;//标记要发送数据
}


/**
  * @brief  Initializes the tcp echo server
  * @param  None
  * @retval None
  */
void tcp_echoserver_init(void)
{
    /* create new tcp pcb */
    tcp_echoserver_pcb = tcp_new();

    if (tcp_echoserver_pcb != NULL)
    {
        err_t err;

        /* bind echo_pcb to port 7 (ECHO protocol) */
        err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);

        if (err == ERR_OK)
        {
            /* start tcp listening for echo_pcb */
            tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);

            /* initialize LwIP tcp_accept callback function */
            tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
        }
        else
        {
            /* deallocate the pcb */
            memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
            printf("Can not bind pcb\n");
        }
    }
    else
    {
        printf("Can not create new pcb\n");
    }
}

/**
  * @brief  This function is the implementation of tcp_accept LwIP callback
  * @param  arg: not used
  * @param  newpcb: pointer on tcp_pcb struct for the newly created tcp connection
  * @param  err: not used
  * @retval err_t: error status
  */
static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    err_t ret_err;
    struct tcp_echoserver_struct *es;

    LWIP_UNUSED_ARG(arg);
    LWIP_UNUSED_ARG(err);

    /* set priority for the newly accepted tcp connection newpcb */
    tcp_setprio(newpcb, TCP_PRIO_MIN);

    /* allocate structure es to maintain tcp connection informations */
    es = (struct tcp_echoserver_struct *)mem_malloc(sizeof(struct tcp_echoserver_struct));
    if (es != NULL)
    {
        es->state = ES_ACCEPTED;
        es->pcb = newpcb;
        es->p = NULL;

        /* pass newly allocated es structure as argument to newpcb */
        tcp_arg(newpcb, es);

        /* initialize lwip tcp_recv callback function for newpcb  */
        tcp_recv(newpcb, tcp_echoserver_recv);

        /* initialize lwip tcp_err callback function for newpcb  */
        tcp_err(newpcb, tcp_echoserver_error);

        /* initialize lwip tcp_poll callback function for newpcb */
        tcp_poll(newpcb, tcp_echoserver_poll, 1);
        lwipdev.remoteip[0]=newpcb->remote_ip.addr&0xff; 		//IADDR4
        lwipdev.remoteip[1]=(newpcb->remote_ip.addr>>8)&0xff;  	//IADDR3
        lwipdev.remoteip[2]=(newpcb->remote_ip.addr>>16)&0xff; 	//IADDR2
        lwipdev.remoteip[3]=(newpcb->remote_ip.addr>>24)&0xff; 	//IADDR1
        ret_err = ERR_OK;
    }
    else
    {
        /*  close tcp connection */
        tcp_echoserver_connection_close(newpcb, es);
        /* return memory error */
        ret_err = ERR_MEM;
    }
    return ret_err;
}

/**
  * @brief  This function is the implementation for tcp_recv LwIP callback
  * @param  arg: pointer on a argument for the tcp_pcb connection
  * @param  tpcb: pointer on the tcp_pcb connection
  * @param  pbuf: pointer on the received pbuf
  * @param  err: error information regarding the reveived pbuf
  * @retval err_t: error code
  */
static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    err_t ret_err;
    uint32_t data_len = 0;
    struct pbuf *q;
    struct tcp_echoserver_struct *es;
    LWIP_ASSERT("arg != NULL",arg != NULL);
    es=(struct tcp_echoserver_struct *)arg;
    if(p==NULL) //从客户端接收到空数据
    {
        es->state=ES_CLOSING;//需要关闭TCP 连接了
        es->p=p;
        ret_err=ERR_OK;
    } else if(err!=ERR_OK)	//从客户端接收到一个非空数据,但是由于某种原因err!=ERR_OK
    {
        if(p)pbuf_free(p);	//释放接收pbuf
        ret_err=err;
    } else if((es->state==ES_ACCEPTED)||(es->state==ES_RECEIVED)) 	//处于连接状态
    {
        if(p!=NULL)  //当处于连接状态并且接收到的数据不为空时将其打印出来
        {
            memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE);  //数据接收缓冲区清零
            for(q=p; q!=NULL; q=q->next) //遍历完整个pbuf链表
            {
                //判断要拷贝到TCP_SERVER_RX_BUFSIZE中的数据是否大于TCP_SERVER_RX_BUFSIZE的剩余空间,如果大于
                //的话就只拷贝TCP_SERVER_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
                if(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) memcpy(tcp_server_recvbuf+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));//拷贝数据
                else memcpy(tcp_server_recvbuf+data_len,q->payload,q->len);
                data_len += q->len;
                if(data_len > TCP_SERVER_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出
            }
            tcp_server_flag|=1<<6;	//标记接收到数据了
            lwipdev.remoteip[0]=tpcb->remote_ip.addr&0xff; 		//IADDR4
            lwipdev.remoteip[1]=(tpcb->remote_ip.addr>>8)&0xff; //IADDR3
            lwipdev.remoteip[2]=(tpcb->remote_ip.addr>>16)&0xff;//IADDR2
            lwipdev.remoteip[3]=(tpcb->remote_ip.addr>>24)&0xff;//IADDR1
            tcp_recved(tpcb,p->tot_len);//用于获取接收数据,通知LWIP可以获取更多数据
            //接收的数据推荐在这里处理,不要再出去处理了
#if TCP_Server_RX_Debug
            printf("TCP_Sever_Re %d.%d.%d.%d:port %d > ",lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2],lwipdev.remoteip[3],tpcb->remote_port&0xFFFF);
            USART1_Send_Len(tcp_server_recvbuf,data_len);
            printf("\r\n");
#endif
            tcp_server_rec_STA=data_len;
            pbuf_free(p);  	//释放内存
            ret_err=ERR_OK;
        }
    } else//服务器关闭了
    {
        tcp_recved(tpcb,p->tot_len);//用于获取接收数据,通知LWIP可以获取更多数据
        es->p=NULL;
        pbuf_free(p); //释放内存
        ret_err=ERR_OK;
    }
    return ret_err;
}

/**
  * @brief  This function implements the tcp_err callback function (called
  *         when a fatal tcp_connection error occurs.
  * @param  arg: pointer on argument parameter
  * @param  err: not used
  * @retval None
  */
static void tcp_echoserver_error(void *arg, err_t err)
{
    struct tcp_echoserver_struct *es;

    LWIP_UNUSED_ARG(err);

    es = (struct tcp_echoserver_struct *)arg;
    if (es != NULL)
    {
        /*  free es structure */
        mem_free(es);
    }
}

/**
  * @brief  This function implements the tcp_poll LwIP callback function
  * @param  arg: pointer on argument passed to callback
  * @param  tpcb: pointer on the tcp_pcb for the current tcp connection
  * @retval err_t: error code
  */
static err_t tcp_echoserver_poll(void *arg, struct tcp_pcb *tpcb)
{
    err_t ret_err;
    struct tcp_echoserver_struct *es;
    es=(struct tcp_echoserver_struct *)arg;
    if(es!=NULL)
    {
        if(tcp_server_flag&(1<<7))	//判断是否有数据要发送
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,strlen((char*)tcp_server_sendbuf),PBUF_POOL);//申请内存
            pbuf_take(es->p,(char*)tcp_server_sendbuf,strlen((char*)tcp_server_sendbuf));
            tcp_echoserver_sent(es,tpcb,es->p->tot_len); 		//轮询的时候发送要发送的数据
            tcp_server_flag&=~(1<<7);  			//清除数据发送标志位
            if(es->p!=NULL)pbuf_free(es->p); 	//释放内存
        } else if(es->state==ES_CLOSING)//需要关闭连接?执行关闭操作
        {
            tcp_echoserver_connection_close(tpcb,es);//关闭连接
        }
        ret_err=ERR_OK;
    } else
    {
        tcp_abort(tpcb);//终止连接,删除pcb控制块
        ret_err=ERR_ABRT;
    }
    return ret_err;
}

/**
  * @brief  This function implements the tcp_sent LwIP callback (called when ACK
  *         is received from remote host for sent data)
  * @param  None
  * @retval None
  */
static err_t tcp_echoserver_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
    struct tcp_echoserver_struct *es;

    LWIP_UNUSED_ARG(len);

    es = (struct tcp_echoserver_struct *)arg;

    if(es->p != NULL)
    {
        /* still got pbufs to send */
        tcp_echoserver_send(tpcb, es);
    }
    else
    {
        /* if no more data to send and client closed connection*/
        if(es->state == ES_CLOSING)
            tcp_echoserver_connection_close(tpcb, es);
    }
    return ERR_OK;
}


/**
  * @brief  This function is used to send data for tcp connection
  * @param  tpcb: pointer on the tcp_pcb connection
  * @param  es: pointer on echo_state structure
  * @retval None
  */
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es)
{
    struct pbuf *ptr;
    err_t wr_err = ERR_OK;

    while ((wr_err == ERR_OK) &&
            (es->p != NULL) &&
            (es->p->len <= tcp_sndbuf(tpcb)))
    {

        /* get pointer on pbuf from es structure */
        ptr = es->p;

        /* enqueue data for transmission */
        wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
#if TCP_Server_TX_Debug
        printf("TCP Server Send:");
        USART1_Send_Len(ptr->payload, ptr->len);
        printf("\r\n");
#endif
        if (wr_err == ERR_OK)
        {
            u16_t plen;

            plen = ptr->len;

            /* continue with next pbuf in chain (if any) */
            es->p = ptr->next;

            if(es->p != NULL)
            {
                /* increment reference count for es->p */
                pbuf_ref(es->p);
            }

            /* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */
            pbuf_free(ptr);

            /* Update tcp window size to be advertized : should be called when received
            data (with the amount plen) has been processed by the application layer */
            tcp_recved(tpcb, plen);
        }
        else if(wr_err == ERR_MEM)
        {
            /* we are low on memory, try later / harder, defer to poll */
            es->p = ptr;
        }
        else
        {
            /* other problem ?? */
        }
    }
}

/**
  * @brief  This functions closes the tcp connection
  * @param  tcp_pcb: pointer on the tcp connection
  * @param  es: pointer on echo_state structure
  * @retval None
  */
static void tcp_echoserver_connection_close(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es)
{

    /* remove all callbacks */
    tcp_arg(tpcb, NULL);
    tcp_sent(tpcb, NULL);
    tcp_recv(tpcb, NULL);
    tcp_err(tpcb, NULL);
    tcp_poll(tpcb, NULL, 0);

    /* delete es structure */
    if (es != NULL)
    {
        mem_free(es);
    }

    /* close tcp connection */
    tcp_close(tpcb);
}

#endif /* LWIP_TCP */

.h

/*
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 * 
 */
#ifndef __TCP_ECHOSERVER_H__
#define __TCP_ECHOSERVER_H__

/* ECHO protocol states */
enum tcp_echoserver_states              //服务器状态
{
  ES_NONE = 0,
  ES_ACCEPTED,
  ES_RECEIVED,
  ES_CLOSING
};

/* structure for maintaing connection infos to be passed as argument 
   to LwIP callbacks*/
struct tcp_echoserver_struct              //服务器缓存区
{
  u8_t state;             /* current connection state */
  struct tcp_pcb *pcb;    /* pointer on the current tcp_pcb */
  struct pbuf *p;         /* pointer on the received/to be transmitted pbuf */
};



void TCP_Server_Send(uint8_t *Data_Dend,uint32_t Len);         //TCP服务器发送函数
void tcp_echoserver_init(void);                                //使用Tcp_Server 必须放在while(1)之前  
void Tcp_Sever_Cloose(void);


#define TCP_SERVER_RX_BUFSIZE	200		//定义tcp server最大接收数据长度   同时作为发送缓存区的长度上限
extern uint8_t tcp_server_recvbuf[TCP_SERVER_RX_BUFSIZE];	       //接收缓存区
extern uint16_t tcp_server_rec_STA;                                //接收状态位,标识未处理的接收数据个数
extern uint8_t tcp_server_flag;                                    //Tcp_Server 逻辑计算用

#define Transparent_transmission_mode    0     //透传模式

#define TCP_Server_RX_Debug 1
#define TCP_Server_TX_Debug 0

#endif /* __TCP_ECHOSERVER */

CLient

.c

/**
  ******************************************************************************
  * @file    tcp_echoclient.c
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    31-July-2013
  * @brief   tcp echoclient application using LwIP RAW API
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "main.h"
#include "memp.h"
#include <stdio.h>
#include <string.h>
#include "tcp_echoclient.h"

#if LWIP_TCP
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

//TCP Client接收数据缓冲区
uint8_t tcp_client_recvbuf[TCP_CLIENT_RX_BUFSIZE];
//TCP服务器发送数据内容
uint8_t *tcp_client_sendbuf="Apollo STM32F4/F7 TCP Client send data\r\n";
//TCP Client 测试全局状态标记变量
//bit7:0,没有数据要发送;1,有数据要发送
//bit6:0,没有收到数据;1,收到数据了.
//bit5:0,没有连接上服务器;1,连接上服务器了.
//bit4~0:保留
uint8_t tcp_client_flag;

u8_t  recev_buf[50];
//__IO uint32_t message_count=0;

//u8_t   data[100];

struct tcp_pcb *echoclient_pcb;


/* ECHO protocol states */
enum echoclient_states
{
    ES_NOT_CONNECTED = 0,
    ES_CONNECTED,
    ES_RECEIVED,
    ES_CLOSING,
};


/* structure to be passed as argument to the tcp callbacks */
struct echoclient
{
    enum echoclient_states state; /* connection status */
    struct tcp_pcb *pcb;          /* pointer on the current tcp_pcb */
    struct pbuf *p_tx;            /* pointer on pbuf to be transmitted */
};


/* Private function prototypes -----------------------------------------------*/
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err);
static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es);
static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb);
static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len);
static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es);
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err);

/* Private functions ---------------------------------------------------------*/

void TCP_Client_Close(void)
{
    struct echoclient *es = NULL;

    /* allocate structure es to maintain tcp connection informations */
    es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));

    if (es != NULL)
    {
        es->state = ES_CLOSING;
        es->pcb = echoclient_pcb;
    }
    tcp_echoclient_connection_close(echoclient_pcb,es);

}


/**
* @brief  Connects to the TCP echo server
* @param  None
* @retval None
*/
void tcp_echoclient_connect(void)
{
    ip_addr_t DestIPaddr;

    /* create new tcp pcb */
    echoclient_pcb = tcp_new();

    if (echoclient_pcb != NULL)
    {
        IP4_ADDR(&DestIPaddr, Remote_IP_ADDR0, Remote_IP_ADDR1, Remote_IP_ADDR2, Remote_IP_ADDR3 );

        /* connect to destination address/port */
        tcp_connect(echoclient_pcb,&DestIPaddr,Remote_PORT,tcp_echoclient_connected);
    }
    else
    {
        /* deallocate the pcb */
        memp_free(MEMP_TCP_PCB, echoclient_pcb);
#ifdef SERIAL_DEBUG
        printf("\n\r can not create tcp pcb");
#endif
    }
}
void Tcp_Client_Send(uint8_t *Data,uint32_t Data_Len)
{
    struct echoclient *es = NULL;
    es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));
    es->state = ES_CONNECTED;
    es->pcb = echoclient_pcb;   //
    /* allocate pbuf */
    es->p_tx = pbuf_alloc(PBUF_TRANSPORT, Data_Len, PBUF_POOL);
    if (es->p_tx)
    {
        /* copy data to pbuf */
        pbuf_take(es->p_tx, (char*)Data, strlen((char*)Data));
    }
    tcp_echoclient_send(es->pcb,es);
}

/**
  * @brief Function called when TCP connection established
  * @param tpcb: pointer on the connection contol block
  * @param err: when connection correctly established err should be ERR_OK
  * @retval err_t: returned error
  */
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    struct echoclient *es = NULL;

    if (err == ERR_OK)
    {
        /* allocate structure es to maintain tcp connection informations */
        es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));

        if (es != NULL)
        {
            es->state = ES_CONNECTED;
            es->pcb = tpcb;


            /* allocate pbuf */
            es->p_tx = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_POOL);

            if (es->p_tx)
            {
                /* pass newly allocated es structure as argument to tpcb */
                tcp_arg(tpcb, es);

                /* initialize LwIP tcp_recv callback function */
                tcp_recv(tpcb, tcp_echoclient_recv);

                /* initialize LwIP tcp_sent callback function */
                tcp_sent(tpcb, tcp_echoclient_sent);

                /* initialize LwIP tcp_poll callback function */
                tcp_poll(tpcb, tcp_echoclient_poll, 1);



                return ERR_OK;
            }
        }
        else
        {
            /* close connection */
            tcp_echoclient_connection_close(tpcb, es);

            /* return memory allocation error */
            return ERR_MEM;
        }
    }
    else
    {
        /* close connection */
        tcp_echoclient_connection_close(tpcb, es);
    }
    return err;
}

/**
  * @brief tcp_receiv callback
  * @param arg: argument to be passed to receive callback
  * @param tpcb: tcp connection control block
  * @param err: receive error code
  * @retval err_t: retuned error
  */
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    struct echoclient *es;
    err_t ret_err;
    uint32_t data_len=0;
    struct pbuf *q;

    LWIP_ASSERT("arg != NULL",arg != NULL);

    es = (struct echoclient *)arg;

    /* if we receive an empty tcp frame from server => close connection */
    if (p == NULL)
    {
        /* remote host closed connection */
        es->state = ES_CLOSING;
        if(es->p_tx == NULL)
        {
            /* we're done sending, close connection */
            tcp_echoclient_connection_close(tpcb, es);    //服务器断开连接
            printf("we're done sending, close connection\r\n");
        }
        else
        {
            /* send remaining data*/
            tcp_echoclient_send(tpcb, es);
        }
        ret_err = ERR_OK;
    }
    /* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
    else if(err != ERR_OK)
    {
        /* free received pbuf*/
        pbuf_free(p);

        ret_err = err;
    }
    else if(es->state == ES_CONNECTED)
    {
        if(p!=NULL)//当处于连接状态并且接收到的数据不为空时
        {
            memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE);  //数据接收缓冲区清零
            for(q=p; q!=NULL; q=q->next) //遍历完整个pbuf链表
            {
                //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于
                //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
                if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据
                else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len);
                data_len += q->len;
                if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出
            }
            tcp_client_flag|=1<<6;		//标记接收到数据了
            tcp_recved(tpcb,p->tot_len);//用于获取接收数据,通知LWIP可以获取更多数据
            lwipdev.remoteip[0]=tpcb->remote_ip.addr&0xff; 		//IADDR4
            lwipdev.remoteip[1]=(tpcb->remote_ip.addr>>8)&0xff; //IADDR3
            lwipdev.remoteip[2]=(tpcb->remote_ip.addr>>16)&0xff;//IADDR2
            lwipdev.remoteip[3]=(tpcb->remote_ip.addr>>24)&0xff;//IADDR1
            lwipdev.remoteport=tpcb->remote_port;
            printf("TCP_Client Recved: %d.%d.%d.%d:port %d  >> ",lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2],lwipdev.remoteip[3],lwipdev.remoteport);
            USART1_Send_Len(tcp_client_recvbuf,data_len);
            printf("\r\n");
            pbuf_free(p);  	//释放内存
            ret_err=ERR_OK;
        }
    }

    /* data received when connection already closed */
    else
    {
        /* Acknowledge data reception */
        tcp_recved(tpcb, p->tot_len);

        /* free pbuf and do nothing */
        pbuf_free(p);
        ret_err = ERR_OK;
    }
    return ret_err;
}

/**
  * @brief function used to send data
  * @param  tpcb: tcp control block
  * @param  es: pointer on structure of type echoclient containing info on data
  *             to be sent
  * @retval None
  */
static void tcp_echoclient_send(struct tcp_pcb *tpcb, struct echoclient * es)
{
    struct pbuf *ptr;
    err_t wr_err = ERR_OK;

    while ((wr_err == ERR_OK) &&
            (es->p_tx != NULL) &&
            (es->p_tx->len <= tcp_sndbuf(tpcb)))
    {

        /* get pointer on pbuf from es structure */
        ptr = es->p_tx;

        /* enqueue data for transmission */
        wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);

        if (wr_err == ERR_OK)
        {
            /* continue with next pbuf in chain (if any) */
            es->p_tx = ptr->next;

            if(es->p_tx != NULL)
            {
                /* increment reference count for es->p */
                pbuf_ref(es->p_tx);
            }

            /* free pbuf: will free pbufs up to es->p (because es->p has a reference count > 0) */
            pbuf_free(ptr);
        }
        else if(wr_err == ERR_MEM)
        {
            /* we are low on memory, try later, defer to poll */
            es->p_tx = ptr;
        }
        else
        {
            /* other problem ?? */
        }
    }
}

/**
  * @brief  This function implements the tcp_poll callback function
  * @param  arg: pointer on argument passed to callback
  * @param  tpcb: tcp connection control block
  * @retval err_t: error code
  */
static err_t tcp_echoclient_poll(void *arg, struct tcp_pcb *tpcb)
{
    err_t ret_err;
    struct echoclient *es;

    es = (struct echoclient*)arg;
    if (es != NULL)
    {
        if (es->p_tx != NULL)
        {
            /* there is a remaining pbuf (chain) , try to send data */
            tcp_echoclient_send(tpcb, es);
        }
        else
        {
            /* no remaining pbuf (chain)  */
            if(es->state == ES_CLOSING)
            {
                /* close tcp connection */
                tcp_echoclient_connection_close(tpcb, es);
            }
        }
        ret_err = ERR_OK;
    }
    else
    {
        /* nothing to be done */
        tcp_abort(tpcb);
        ret_err = ERR_ABRT;
    }
    return ret_err;
}

/**
  * @brief  This function implements the tcp_sent LwIP callback (called when ACK
  *         is received from remote host for sent data)
  * @param  arg: pointer on argument passed to callback
  * @param  tcp_pcb: tcp connection control block
  * @param  len: length of data sent
  * @retval err_t: returned error code
  */
static err_t tcp_echoclient_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
    struct echoclient *es;

    LWIP_UNUSED_ARG(len);

    es = (struct echoclient *)arg;

    if(es->p_tx != NULL)
    {
        /* still got pbufs to send */
        tcp_echoclient_send(tpcb, es);
    }

    return ERR_OK;
}

/**
  * @brief This function is used to close the tcp connection with server
  * @param tpcb: tcp connection control block
  * @param es: pointer on echoclient structure
  * @retval None
  */
static void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct echoclient * es )
{
    /* remove callbacks */
    tcp_recv(tpcb, NULL);
    tcp_sent(tpcb, NULL);
    tcp_poll(tpcb, NULL,0);

    if (es != NULL)
    {
        mem_free(es);
    }

    /* close tcp connection */
    tcp_close(tpcb);

}

#endif /* LWIP_TCP */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

.h

/**
  ******************************************************************************
  * @file    udp_echoclient.h
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    31-July-2013 
  * @brief   Header file for udp_echoclient.c
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/  
#ifndef __UDP_ECHOCLIENT_H__
#define __UDP_ECHOCLIENT_H__

/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void udp_echoclient_connect(void);

#endif /* __UDP_ECHOCLIENT_H__ */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

UDP

.c

/**
  ******************************************************************************
  * @file    udp_echoserver.c
  * @author  MCD Application Team
  * @version V1.1.0
  * @date    31-July-2013
  * @brief   UDP echo server
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include <string.h>
#include <stdio.h>
#include "LWIP_COM.h"
#include "udp_echoserver.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/
uint8_t udp_demo_recvbuf[UDP_DEMO_RX_BUFSIZE];
struct udp_pcb *upcb;             //全局用
 ip_addr_t Remote_addr;//发送的目标地址   注意写入数值不可以直接等于,必须用 IP4_ADDR 写入地址
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p,const ip_addr_t *addr, u16_t port);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Initialize the server application.
  * @param  None
  * @retval None
  */
void udp_echoserver_init(void)
{
   err_t err;
   /* Create a new UDP control block  */
   upcb = udp_new();
	printf("udp_new IP_ADDR_ANY Port:%d\r\n",UDP_Server_PORT);
   if (upcb)
   {
     /* Bind the upcb to the UDP_PORT port */
     /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
      err = udp_bind(upcb, IP_ADDR_ANY, UDP_Server_PORT);
      if(err == ERR_OK)
      {
        /* Set a receive callback for the upcb */
        udp_recv(upcb, udp_echoserver_receive_callback, NULL);
      }
      else
      {
        udp_remove(upcb);
        printf("can not bind pcb");
      }
   }
   else
   {
     printf("can not create pcb");
   } 
}

/**
  * @brief This function is called when an UDP datagrm has been received on the port UDP_PORT.
  * @param arg user supplied argument (udp_pcb.recv_arg)
  * @param pcb the udp_pcb which received data
  * @param p the packet buffer that was received
  * @param addr the remote IP address from which the packet was received
  * @param port the remote port from which the packet was received
  * @retval None
  */
void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
	uint8_t UDP_Server_remoteip[4];
	uint32_t data_len = 0;
	struct pbuf *q;
	printf("udp_server_receive:");
	UDP_Server_remoteip[0]=addr->addr&0xff; 		//IADDR4
	UDP_Server_remoteip[1]=(addr->addr>>8)&0xff;  	//IADDR3
	UDP_Server_remoteip[2]=(addr->addr>>16)&0xff; 	//IADDR2
	UDP_Server_remoteip[3]=(addr->addr>>24)&0xff; 	//IADDR1
	printf("from %d.%d.%d.%d:%d >",UDP_Server_remoteip[0],UDP_Server_remoteip[1],UDP_Server_remoteip[2],UDP_Server_remoteip[3],port);
	
	IP4_ADDR(&Remote_addr, UDP_Server_remoteip[0], UDP_Server_remoteip[1], UDP_Server_remoteip[2], UDP_Server_remoteip[3] );  //写入远端地址,用于发送
	
	if(p!=NULL)  //当处于连接状态并且接收到的数据不为空时将其打印出来
	{
		memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE);  //数据接收缓冲区清零
		for(q=p;q!=NULL;q=q->next)  //遍历完整个pbuf链表
		{
			//判断要拷贝到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; //超出TCP客户端接收数组,跳出	
		}
		//接收的数据推荐在这里处理,不要再出去处理了
		//tcp_server_rec_STA=data_len;
		USART1_Send_Len(udp_demo_recvbuf,data_len);
		printf(" Len %d\r\n",p->len);
	}
  /* Free the p buffer */
  pbuf_free(p);
   
}

void UDP_Send(uint8_t *Data,uint8_t Len)
{
	struct pbuf *ptr;
	ptr=pbuf_alloc(PBUF_TRANSPORT,Len,PBUF_POOL); //申请内存
	if(Remote_addr.addr)
	{
		printf("Send %d.%d.%d.%d:%d > ",(Remote_addr.addr>>0)&0xFF,(Remote_addr.addr>>8)&0xFF,(Remote_addr.addr>>16)&0xFF,(Remote_addr.addr>>24)&0xFF,UDP_Remote_PORT);
		USART1_Send_Len(Data,Len); 
		printf("\r\n");		
		/* Connect to the remote client */
	  udp_connect(upcb, &Remote_addr, UDP_Remote_PORT);
	  /* Tell the client that we have accepted it */
		if(ptr)
		{
			ptr->payload=(void*)Data; 
			udp_send(upcb,ptr);	//udp发送数据 
			pbuf_free(ptr);//释放内存
		}
	  /* free the UDP connection, so we can accept new clients */
	    udp_disconnect(upcb);
		}else{
			pbuf_free(ptr);//释放内存
			printf("先用远端主机给单片机发送一条信息\r\n");
		}

}

void UDP_Close(void)
{
	udp_disconnect(upcb); 
	udp_remove(upcb);		//断开UDP连接 
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

.h

/*
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved. 
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 * 
 */
#ifndef __ECHO_H__
#define __ECHO_H__



#define UDP_DEMO_RX_BUFSIZE		200		//定义udp最大接收数据长度 


extern struct udp_pcb *upcb;
extern uint8_t udp_demo_recvbuf[UDP_DEMO_RX_BUFSIZE];	//UDP接收数据缓冲区 


void udp_echoserver_init(void);
void UDP_Send(uint8_t *Data,uint8_t Len);
void UDP_Close(void);
#endif /* __MINIMAL_ECHO_H */

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-06-01 15:23:19  更:2022-06-01 15:23:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:57:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码