里面提到的资源和写完的例程放出来,
链接:https://pan.baidu.com/s/1vdPKbLk7jg0Nvw0gc5qmEQ?pwd=dri2
提取码:dri2
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目录下有各种例程,都是放进工程稍微改一下变量命名就能直接用的
里面的文章来源:https://www.toymoban.com/news/detail-408496.html
lwipopts.h文件在移植LWIP时也很有用
后续怎么移植的我不再赘述,其实就是改完编译错误后加一些自己需要的功能逻辑,目前写的也不是很完善,也够用了
以下是我改的一些app
首先是一个前置文件 LWIP_COM文章来源地址https://www.toymoban.com/news/detail-408496.html
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>© 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>© 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>© 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 */
到了这里,关于STM32F107+LAN8720A使用STM32cubeMX配置网络连接+tcp主从机+UDP app的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!