使用标准库对STM32F407ZGT6移植LWIP(逻机-全网最全)

本文详细介绍了如何使用STM32CubeMX在STM32F407ZGT6上移植LWIP协议栈,包括移植准备、添加和修改ST以太网库、添加LWIP源文件、处理中间文件、修改LWIP源码以及配置和下载验证。过程中涉及到STM32F407的以太网库、LAN8720驱动、LWIP源码的裁剪和配置,以及LWIP与硬件的连接设置。
摘要由CSDN通过智能技术生成

使用STM32CubeM对F407ZGT6移植LWIP(全网最全)
使用标准库对STM32F407ZGT6移植LWIP(逻机-全网最全)
基于STM32单片机的LwIP协议(一)网络协议简介
基于STM32单片机的LwIP协议(二)LwIP简介
基于STM32单片机的LwIP协议(三)开发平台介绍
基于STM32单片机的LwIP协议(四)LwIP的网络接口管理
基于STM32单片机的LwIP协议(五)LwIP的TCP_server
基于STM32单片机的LwIP协议(六)LwIP的TCP_client

 次项目工程是基于正点原子STM32F4探索者开发板移植LwIP无操作系统的移植笔记

1、移植准备工作

1.1 基础工程

在移植之前我们需要一个基础工程,因为我们要用到内存管理,因此这里我们使用实验37内存管理实验作为基础工程,我们在这个工程的基础上完成本章的移植过程。

本章我们要使用到 USMART 组件,因此我们要在内存管理实验的工程上添加 USMART 组件,如果已经添加了的话就不用再添加了,关于 USMART 组件的使用请参考我们的:STM32F4开发指南实验 14 USMART 实验。将试验14USMART 实验下的USMART文件夹复制到当前的工程目录,然后将USMART组件添加到工程中。
 添加完成后会报下面的错误,是由于USMAT库使用了定时器,所以我们要在FWLIB中添加

1.2 ST 以太网库下载

因为 STM32F407 带有以太网 MAC 模块,因此 ST 也提供了以太网库,我们可以在 ST 官网:http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1734/PF257906#下载,下载界面如图 所示。下载解压后为名为:STM32F4x7_ETH_LwIP_V1.1.0,我们已经将解压后的以太网库放到光盘中,在软件资料文件夹下的 LWIP 学习资料文件夹中。

1.3 LWIP 文件下载

在移植的过程中我们需要两个文件,LWIP 源码和 LWIP 官方的例程,我们可以在 LWIP 官
网:http://download.savannah.gnu.org/releases/lwip/下载这两个文件,如图所示为我们需要下载的两个文件。

其中 lwip-2.2.2.zip 为 LWIP 的官方源码,contrib-2.1.0.zip 包含官方的一些例程和我们移植时所需要的一些头文件。
图 2‑4 下载解压后得到的源码包和 contrib 包

2 添加及修改ST 以太网库

2.1、添加以太网库

准备好移植所需要的文件,就开始 LWIP 的移植。我们首先将 ST 的以太网库添加到工程中,将STM32F4x7_ETH_LwIP_V1.1.0 文件中 Libraries文件夹下的STM32F4x7_ETH_Driver文件复制到我们基础工程的FWLIB文件夹下,如图所示。

然后删除这个文件夹中的inc和scr两个文件夹,并将STM32F4xx_StdPeriph_Driver文件夹复制到这个文件夹中,其实STM32F4xx_StdPeriph_Driver文件夹中就是inc和scr两个文件夹文件夹,存放的是标准库问价。这样做只是为了好看一致!

然后打开keil工程发现库前面加了感叹号,因为我们刚刚改变了库的路径,故删除掉重新添加一遍。

STM32F4x7_ETH_Driver文件夹中一共有 3 个文件,stm32f4x7_eth.hstm32f4x7_eth.cstm32f4x7_eth_conf_template.hstm32f4x7_eth.h 为头文件,这个很好理解,stm32f4x7_eth.c为ST的以太网库,里面有很多关于STM32F4X7的以太网的函数,stm32f4x7_eth_conf_template.h里面定义了一些关于操作PHY芯片的信息,为了方便移植我们将stm32f4x7_eth_conf_template.h重命名为stm32f4x7_eth_conf.h。最后我们将 stm32f4x7_eth.c 添加到我们的工程中,并且添加头文件路径,添加完成后的基础工程如图 所示。
 这时候编译工程是会报错的,先不用管,继续往下看。

2.2、修改 stm32f4x7_eth_conf.h 文件

ST 提供给我们的 stm32f4x7_eth_conf.h文件只是一个参考文件,在这个文件是以DP83848为例编写的,而我们的 STM32F407 开发板使用的是 LAN8720,因此我们要根据LAN8720做一定的修改,修改后的 stm32f4x7_eth_conf.h 文件代码如下。

#ifndef __STM32F4x7_ETH_CONF_H
#define __STM32F4x7_ETH_CONF_H
#include "stm32f4xx.h"

#define USE_ENHANCED_DMA_DESCRIPTORS

//如果使用自己定义的延时函数的话就注销掉下面一行代码,否则使用
//默认的低精度延时函数

//#define USE_Delay    	//使用默认延时函数,因此注销掉
#ifdef USE_Delay
	#include "main.h"               
	#define _eth_delay_    Delay     //Delay为用户自己提供的高精度延时函数
                                    
#else
	#define _eth_delay_    ETH_Delay //默认的_eth_delay功能函数延时精度差
#endif

#ifdef  CUSTOM_DRIVER_BUFFERS_CONFIG
	//重新定义以太网接收和发送缓冲区的大小和数量
	#define ETH_RX_BUF_SIZE    ETH_MAX_PACKET_SIZE //接收缓冲区的大小
	#define ETH_TX_BUF_SIZE    ETH_MAX_PACKET_SIZE //发送缓冲区的大小
	#define ETH_RXBUFNB        20                  //接收缓冲区数量
	#define ETH_TXBUFNB        5                   //发送缓冲区数量
#endif

//*******************PHY配置块*******************
#ifdef USE_Delay
	#define PHY_RESET_DELAY    ((uint32_t)0x000000FF)  	//PHY复位延时
	#define PHY_CONFIG_DELAY   ((uint32_t)0x00000FFF) 	//PHY配置延时
	#define ETH_REG_WRITE_DELAY ((uint32_t)0x00000001)	//向以太网寄存器写数据时的延时
#else
	#define PHY_RESET_DELAY    ((uint32_t)0x000FFFFF)	//PHY复位延时
	#define PHY_CONFIG_DELAY   ((uint32_t)0x00FFFFFF)	//PHY配置延时
	#define ETH_REG_WRITE_DELAY ((uint32_t)0x0000FFFF)	//向以太网寄存器写数据时的延时
#endif

//LAN8720 PHY芯片的状态寄存器
#define PHY_SR				((uint16_t)31) 		//LAN8720的PHY状态寄存器地址
#define PHY_SPEED_STATUS    ((uint16_t)0x0004) 	//LAN8720 PHY速度值掩码
#define PHY_DUPLEX_STATUS   ((uint16_t)0x00010) //LAN8720 PHY连接状态值掩码  
#endif 

在上面代码中我们定义了操作 PHY 芯片时需要用到的延时配置,也定义了 LAN8720 的状态寄存器地址和 LAN8720 中的速度值、连接状态的掩码。通过读取 LAN8720 的状态寄存器并且与这两个掩码做计算即可得到网络的连接速度和双工模式。到这里我们编译一下工程,没有任何错误,如果有错误的话根据错误类型检查和修改工程。

2.3、修改 stm32f4x7_eth.c 文件

在 stm32f4x7_eth.c 文件中针对不同的平台定义了四个数组:Rx_Buff[]、Tx_Buff[]、DMARxDscrTab[]和 DMATxDscrTab[],这四个数组占用了大量的 RAM。我们在这里将这四个变量屏蔽掉,如图所示。在其他文件中会采用内存管理的方式为这 4 个数组分配内存,这样我们就可以使用外部 SRAM,减少对 STM32F407 内部 RAM 的使用

2.4、添加LAN8720和MAC/DMA驱动

打开我们的 LWIP 无操作系统移植实验的 HARDWARE 文件夹,在里面有一个 ETHERNET文件,在这个文件中有lan8720.clan8720.h 这两个文件,这两个文件里面包含LAN8720 和STM32F407 自带的 MAC 的驱动程序,大家在移植的时候将 ETHERNET 文件拷贝到自己的HARDWARE 文 件 中 , 并 且 将lan8720.c添 加 到 工 程 中 。 在 这 里 我 们 还 要 使 用 到stm32f4xx_syscfg.c文件,这个文件是官方的标准外设库文件,我们将其加入到工程中。添加完lan8720.c 和 stm32f4xx_syscfg.c 文件后的工程如图所示。

至此网卡驱动添加完成,我们编译一下提示如上图所示错误,这是因为在以太网 DMA接收中断服务函数 ETH_IRQHandler()中调用了lwip_pkt_handle()函数,而这个函数没有在lan8720.c文件中定义,这个错误提示不用管,lwip_pkt_handle()函数后续会讲解。

3、添加LwIP源文件

在工程目录下新建一个LWIP文件夹,在里面添加前面下载的的lwip文件夹lwip-2.1.2文件夹。(准备将 LwIP 源码添加到工程中,但是 LwIP源码太大了,我们不需要那么多东西,所以我们只需要将 LwIP 源码中的 src 文件文件夹添加进去即可,但是我发现 src 表示源码,但是不够明显,无法一眼就知道它是 LwIP 中的源码,那我们直接把文件夹重命名为“LwIP”,这样子就能让别人一目了然知道文件夹是什么内容了。)

在前面的章节中也讲解了 LwIP 源码文件夹的功能及作用,那么我们现在直接添加到工程分组中即可,首先我们在工程中创建4个与 LwIP 相关的工程分组,其中三个分别用于存放 LwIP 源码中的三个文件,其对应关系具体见图。

每个分组中都添加对应文件夹下的源码,添加完成后的源码具体见下图

3.1、LWIP_api分组

3.2、LWIP_core分组

3.3、LWIP_netif分组

3.4、添加分组头文件

 添加完这些文件后编译会报错,暂时先不管,继续往下看!

4、添加中间文件

我们上面只是将 LWIP 源文件和以太网的驱动都添加到工程中,要将以太网驱动和 LWIP连接起来还需要一些其他文件,而这些文件非常重要,我们下面就讲解如何添加这些文件。

4.1、添加arch文件

打开我们的网络实验 1 LWIP 无操作系统移植实验的 LWIP 文件夹可以发现有一个 arch 文件夹,将这个文件夹复制到自己工程中,在 arch 中有 5 个文件 cc.h、cpu.h、perf.h、sys_arch.h和 sys_arch.c。根据 sys_arch.txt 中的描述,cc.h 主要完成了协议栈内部使用的数据类型的定义,如果使用操作系统的话还有临界代码区保护等等。

LWIP 内核中有许多的周期性的定时器,相对应的定时处理函数也需要被周期性调用的,因为没有使用操作系统,所有需要我们自己使用定时器来实现。这里我们使用 STM32F407 定时器 3 提供这个系统时钟,定时器 3 定时周期为 10ms,定时器 3 的中断服务函数如下,lwip_localtime 是一个全局变量,在 lwip_comm.c 文件中有定义。我们新建 timer.c 文件放关于定时器 3 的程序,然后将 timer.c 添加到 HARDWARE 组下面,并且添加相应的头文件路径。

添加完这些文件后编译会报错,暂时先不管,继续往下看!

4.2、添加LWIP通用文件

打开我们的网络实验 LWIP无操作系统移植实验的LWIP文件夹可以发现有一个lwip_app文件夹,将这个文件夹复制到自己工程中,lwip_app 文件夹用来放我们以后所有实验的代码。在lwip_app下有一个lwip_comm文件夹,这个文件中有lwip_comm.clwip_comm.hlwipopts.h这三个文件,lwip_comm.clwip_comm.h 是将 LWIP 源码和前面的以太网驱动库结合起来的桥梁!这两个文件非常重要,这两个文件有 ALIENTEK 提供。lwipopts.h 是用来裁剪和配置 LWIP的文件,以后我们想要使用 LWIP 的什么功能的话就在这个文件中配置就行了。

同样的,我们在工程中新建一个LWIP_app分组,并将lwip_comm.c文件添加到这个分组中并且添加相应的头文件路径,如图 所示。

4.3、添加 ethernetif.h 文件

打开我们的网络实验1LWIP 无操作系统移植实验,LWIP->lwip1.4.1->src->include->netif中我们会发现有个ethernetif.h文件,这个文件在 LWIP 源码中是不存在的,这个文件由ALIENTEK 提供,将ethernetif.h 文件复制到自己工程的相应位置,如下图所示。

5、LwIP源码修改

在上面添加中间文件完成后,我们还有修改一下 LWIP 的源码,中间文件连接 LWIP 底层驱动和 LWIP,这样或多或少会对 LWIP 的源码做出一点小的改动,下面我们就讲解如何修改LWIP 源码。

5.1、修改 LWIP 源文件名字

我们按路径:lwip-1.4.1->src->core 可以发现在 core 文件下有一个 sys.c 文件,按路径lwip-1.4.1->src->include->lwip 可以发现有一个sys.h 文件。sys.c 和 sys.h 这两个文件和我们的SYSTEM 文件中的 sys.c 和 sys.h 重名,因此我们将 LWIP 中 sys.c 和 sys.h 改为 lwip_sys.c 和lwip_sys.h,然后在工程中将 LWIP 源码里面的#include “sys.h”代码也要改掉,更改为#include“lwip_sys.h”。

5.2、修改 ethernetif.c 文件

ethernetif.c 的文件路径为:LWIP->lwip1.4.1->src->netif。用我们网络实验 1 LWIP 无操作系统移植实验中的ethernetif.c 文件替代 LWIP 源码中的这个文件,在这个文件中有 5 个函数。

#include "netif/ethernetif.h" 
#include "lan8720.h"  
#include "lwip_comm.h" 
#include "netif/etharp.h"  
#include "string.h"  

//由ethernetif_init()调用用于初始化硬件
//netif:网卡结构体指针 
//返回值:ERR_OK,正常
//       其他,失败
static err_t low_level_init(struct netif *netif)
{
#ifdef CHECKSUM_BY_HARDWARE
	int i; 
#endif 
	netif->hwaddr_len = ETHARP_HWADDR_LEN; //设置MAC地址长度,为6个字节
	//初始化MAC地址,设置什么地址由用户自己设置,但是不能与网络中其他设备MAC地址重复
	netif->hwaddr[0]=lwipdev.mac[0]; 
	netif->hwaddr[1]=lwipdev.mac[1]; 
	netif->hwaddr[2]=lwipdev.mac[2];
	netif->hwaddr[3]=lwipdev.mac[3];
	netif->hwaddr[4]=lwipdev.mac[4];
	netif->hwaddr[5]=lwipdev.mac[5];
	netif->mtu=1500; //最大允许传输单元,允许该网卡广播和ARP功能

	netif->flags = NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP|NETIF_FLAG_LINK_UP;
	
	ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); //向STM32F4的MAC地址寄存器中写入MAC地址
	ETH_DMATxDescChainInit(DMATxDscrTab, Tx_Buff, ETH_TXBUFNB);
	ETH_DMARxDescChainInit(DMARxDscrTab, Rx_Buff, ETH_RXBUFNB);
#ifdef CHECKSUM_BY_HARDWARE 	//使用硬件帧校验
	for(i=0;i<ETH_TXBUFNB;i++)	//使能TCP,UDP和ICMP的发送帧校验,TCP,UDP和ICMP的接收帧校验在DMA中配置了
	{
		ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
	}
#endif
	ETH_Start(); //开启MAC和DMA				
	return ERR_OK;
} 
//用于发送数据包的最底层函数(lwip通过netif->linkoutput指向该函数)
//netif:网卡结构体指针
//p:pbuf数据结构体指针
//返回值:ERR_OK,发送正常
//       ERR_MEM,发送失败
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
	u8 res;
	struct pbuf *q;
	int l = 0;
	u8 *buffer=(u8 *)ETH_GetCurrentTxBuffer(); 
	for(q=p;q!=NULL;q=q->next) 
	{
		memcpy((u8_t*)&buffer[l], q->payload, q->len);
		l=l+q->len;
	} 
	res=ETH_Tx_Packet(l); 
	if(res==ETH_ERROR)return ERR_MEM;//返回错误状态
	return ERR_OK;
}  
///用于接收数据包的最底层函数
//neitif:网卡结构体指针
//返回值:pbuf数据结构体指针
static struct pbuf * low_level_input(struct netif *netif)
{  
	struct pbuf *p, *q;
	u16_t len;
	int l =0;
	FrameTypeDef frame;
	u8 *buffer;
	p = NULL;
	frame=ETH_Rx_Packet();
	len=frame.length;//得到包大小
	buffer=(u8 *)frame.buffer;//得到包数据地址 
	p=pbuf_alloc(PBUF_RAW,len,PBUF_POOL);//pbufs内存池分配pbuf
	if(p!=NULL)
	{
		for(q=p;q!=NULL;q=q->next)
		{
			memcpy((u8_t*)q->payload,(u8_t*)&buffer[l], q->len);
			l=l+q->len;
		}    
	}
	frame.descriptor->Status=ETH_DMARxDesc_OWN;//设置Rx描述符OWN位,buffer重归ETH DMA 
	if((ETH->DMASR&ETH_DMASR_RBUS)!=(u32)RESET)//当Rx Buffer不可用位(RBUS)被设置的时候,重置它.恢复传输
	{ 
		ETH->DMASR=ETH_DMASR_RBUS;//重置ETH DMA RBUS位 
		ETH->DMARPDR=0;//恢复DMA接收
	}
	return p;
}
//网卡接收数据(lwip直接调用)
//netif:网卡结构体指针
//返回值:ERR_OK,发送正常
//       ERR_MEM,发送失败
err_t ethernetif_input(struct netif *netif)
{
	err_t err;
	struct pbuf *p;
	p=low_level_input(netif);//liuyao--
	if(p==NULL) return ERR_MEM;
	err=netif->input(p, netif);//input
	if(err!=ERR_OK)
	{
		LWIP_DEBUGF(NETIF_DEBUG,("ethernetif_input: IP input error\n"));
		pbuf_free(p);
		p = NULL;
	} 
	return err;
} 
//使用low_level_init()函数来初始化网络
//netif:网卡结构体指针
//返回值:ERR_OK,正常
//       其他,失败
err_t ethernetif_init(struct netif *netif)
{
	LWIP_ASSERT("netif!=NULL",(netif!=NULL));
#if LWIP_NETIF_HOSTNAME			//LWIP_NETIF_HOSTNAME 
	netif->hostname="lwip";  	//初始化名称
#endif 
	netif->name[0]=IFNAME0; 	//初始化变量netif的name字段
	netif->name[1]=IFNAME1; 	//在文件外定义这里不用关心具体值
	netif->output=etharp_output;//IP层发送数据包函数
	netif->linkoutput=low_level_output;//ARP模块发送数据包函数
	low_level_init(netif); 		//底层硬件初始化函数
	return ERR_OK;
}

5.3、修改 mem.c 和 和 memp.c 文件

根据我们前面讲过的 LWIP 动态内存管理技术,我们知道 LWIP 有一个内存堆 ram_heap 和内存池 memp_memory,这两个是 LWIP 的内存来源。这两个分别在 mem.c 和 memp.c 中,我们将这两个数组改用 ALIENTEK 的内存分配函数对其进行内存分配。在 mem.c 文件中我们将ram_heap 数组注销掉,定义为指向 u8_t 的指针,如图所示。
 同样我们也将 memp.c 文件中将 memp_memory 数组屏蔽掉改为指针,如图 所示。
 在 memp.c 文件中添加memp_get_memorysize()函数,如图所示。

5.4、修改 icmp.c 文件

我们需要修改 icmp.c 文档使其支持硬件帧校验,修改部分如图所示。图中红框部分为 icmp.c 的源码,我们将其注销掉,蓝框部分是我们需要添加进去的代码,这部分代码是由 ST提供的。

6、LwIP裁剪与配置

在 LWIP 的源码中有个opt.h的文件,这个文件是裁剪和配置 LWIP 的,不过我们最好不要直接在opt.h 里面做修改,我们可以打开opt.h 文件看一下,里面的配置都是条件编译的,如果我们在其他地方有定义过的话那么在 opt.h 里面的定义不起作用了。所以我们可以新建一个.h的文件来裁剪和配置 LWIP,我们前面提过在 LWIP->lwip_app->lwip_comm 下有一个 lwipopts.h的文件,这个文件就是用来裁剪与配置lwipopts.h 的,lwipopts.h 配置代码如下。

/**
	LWIP配置文件,通过此文件可以选择LWIP的功能,
	此文件基于opt.h文件,opt.h是LWIP"出厂"时原装的文件,由Adam等人编写
	而lwipopt.h的作者是ST的,它集合了lwip中常常需要改动的地方
	和针对ST所特有的配置选项添加进来了,这两个文件里边都配置了的
	选项以后者为准,不是共有的选项以他们各自的配置为准
*/

#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

#define SYS_LIGHTWEIGHT_PROT    0
//NO_SYS==1:不使用操作系统
#define NO_SYS                  1  //不使用UCOS操作系统
//使用4字节对齐模式
#define MEM_ALIGNMENT           4  
//MEM_SIZE:heap内存的大小,如果在应用中有大量数据发送的话这个值最好设置大一点 
#define MEM_SIZE                16000 //内存堆大小
//MEMP_NUM_PBUF:memp结构的pbuf数量,如果应用从ROM或者静态存储区发送大量数据时,这个值应该设置大一点
#define MEMP_NUM_PBUF           10
//MEMP_NUM_UDP_PCB:UDP协议控制块(PCB)数量.每个活动的UDP"连接"需要一个PCB.
#define MEMP_NUM_UDP_PCB        6
//MEMP_NUM_TCP_PCB:同时建立激活的TCP数量
#define MEMP_NUM_TCP_PCB        10
//MEMP_NUM_TCP_PCB_LISTEN:能够监听的TCP连接数量
#define MEMP_NUM_TCP_PCB_LISTEN 6
//MEMP_NUM_TCP_SEG:最多同时在队列中的TCP段数量
#define MEMP_NUM_TCP_SEG        15
//MEMP_NUM_SYS_TIMEOUT:能够同时激活的timeout个数
#define MEMP_NUM_SYS_TIMEOUT    8
/* ---------- Pbuf选项---------- */
//PBUF_POOL_SIZE:pbuf内存池个数. 
#define PBUF_POOL_SIZE          20
//PBUF_POOL_BUFSIZE:每个pbuf内存池大小. 
#define PBUF_POOL_BUFSIZE       512
/* ---------- TCP选项---------- */
#define LWIP_TCP                1  //为1是使用TCP
#define TCP_TTL                 255//生存时间
/*当TCP的数据段超出队列时的控制位,当设备的内存过小的时候此项应为0*/
#define TCP_QUEUE_OOSEQ         0
//最大TCP分段
#define TCP_MSS                 (1500 - 40)	  //TCP_MSS = (MTU - IP报头大小 - TCP报头大小
//TCP发送缓冲区大小(bytes).
#define TCP_SND_BUF             (4*TCP_MSS)
//TCP_SND_QUEUELEN: TCP发送缓冲区大小(pbuf).这个值最小为(2 * TCP_SND_BUF/TCP_MSS) */
#define TCP_SND_QUEUELEN        (2* TCP_SND_BUF/TCP_MSS)
//TCP发送窗口
#define TCP_WND                 (2*TCP_MSS)
/* ---------- ICMP选项---------- */
#define LWIP_ICMP                 1 //使用ICMP协议
/* ---------- DHCP选项---------- */
//当使用DHCP时此位应该为1,LwIP 0.5.1版本中没有DHCP服务.
#define LWIP_DHCP               1
/* ---------- UDP选项 ---------- */ 
#define LWIP_UDP                1 //使用UDP服务
#define UDP_TTL                 255 //UDP数据包生存时间
/* ---------- Statistics options ---------- */
#define LWIP_STATS 0
#define LWIP_PROVIDE_ERRNO 1
/*
   --------------------------------------
   ---------- 帧校验和选项----------
   --------------------------------------
*/
//STM32F4x7允许通过硬件识别和计算IP,UDP和ICMP的帧校验和
#define CHECKSUM_BY_HARDWARE //定义CHECKSUM_BY_HARDWARE,使用硬件帧校验
#ifdef CHECKSUM_BY_HARDWARE
  //CHECKSUM_GEN_IP==0: 硬件生成IP数据包的帧校验和
  #define CHECKSUM_GEN_IP                 0
  //CHECKSUM_GEN_UDP==0: 硬件生成UDP数据包的帧校验和
  #define CHECKSUM_GEN_UDP                0
  //CHECKSUM_GEN_TCP==0: 硬件生成TCP数据包的帧校验和
  #define CHECKSUM_GEN_TCP                0 
  //CHECKSUM_CHECK_IP==0: 硬件检查输入的IP数据包帧校验和
  #define CHECKSUM_CHECK_IP               0
  //CHECKSUM_CHECK_UDP==0: 硬件检查输入的UDP数据包帧校验和
  #define CHECKSUM_CHECK_UDP              0
  //CHECKSUM_CHECK_TCP==0: 硬件检查输入的TCP数据包帧校验和
  #define CHECKSUM_CHECK_TCP              0
#else
  /* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
  #define CHECKSUM_GEN_IP                 1
  /* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
  #define CHECKSUM_GEN_UDP                1
  /* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
  #define CHECKSUM_GEN_TCP                1
  /* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
  #define CHECKSUM_CHECK_IP               1
  /* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
  #define CHECKSUM_CHECK_UDP              1
  /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
  #define CHECKSUM_CHECK_TCP              1
#endif
/*
   ----------------------------------------------
   ---------- SequentialAPI选项----------
   ----------------------------------------------
*/
//LWIP_NETCONN==1:使能NETCON函数(要求使用api_lib.c)
#define LWIP_NETCONN                    0
/*
   ------------------------------------
   ---------- Socket API选项----------
   ------------------------------------
*/
//LWIP_SOCKET==1:使能Sicket API(要求使用sockets.c)
#define LWIP_SOCKET                     0
#define LWIP_COMPAT_MUTEX               1
#define LWIP_SO_RCVTIMEO                1 //通过定义LWIP_SO_RCVTIMEO使能netconn结构体中recv_timeout,使用recv_timeout可以避免阻塞线程
/*
   ----------------------------------------
   ---------- Lwip调试选项----------
   ----------------------------------------
*/
//#define LWIP_DEBUG                     1 //开启DEBUG选项
#define ICMP_DEBUG                      LWIP_DBG_OFF //开启/关闭ICMPdebug
#endif /* __LWIPOPTS_H__ */

7、下载验证

开发板与电脑通过网线连接,把程序下载到开发板中

然后在电脑上打开cmd终端,输入

ping 192.168.1.30

 是ping不通的,具体操作如下

连接设置

在代码编译成功以后,我们下载代码到开发板中,通过网线连接开发板到路由器上,如果没有路由器的话也可以直接连接到电脑的RJ45接口上,由于 LAN8720 具有自动翻转功能,所以连接电脑 RJ45 时就不需要更换网线。但是如果连接到电脑的 RJ45 接口上那么开发板就不能使用 DHCP 功能,需要使用静态地址,我们例程中的默认静态 IP 地址:192.168.1.30,子网掩码:255.255.255.0,默认网关:192.168.1.1。连接上电脑端的 RJ45 以后我们还需要更改一下电脑的网络设置,步骤如下。

1、打开控制面板中的“网络和共享中心”,如图所示。
在这里插入图片描述
2、打开“网络和共享中心”以后点击右侧的“更改适配器设置”
在这里插入图片描述
3、打开“更改适配器设置”后,点击以太网—>属性

 5、点击“属性”以后出现如图所示对话框,选中“Internet 协议版本 4(TCP/IPv4)”并点击“属性”。点击“属性”后选择“使用下面的 IP 地址”和“使用下面的 DNS 服务器地址”。在 IP 地址栏填入:192.168.1.x(x 为 2-254),子网掩码:255.255.255.0 默认网关:192.168.1.1,首选 DNS 服务器:192.168.1.1,最后记得点击“确定”。注意!电脑的IP 地址一定要和开发板的 IP 地址在一个网络内!以后我们的实验都是连接到路由器上的,如果没有路由器的话都可以使用上面这种方法这种方法完成实验,只是不能使用 DHCP 服务。
 打开串口调试助手,复位一下开发板。这里我们开启了 DHCP,大家也可以自行尝试一下关闭 DHCP 使用静态 IP 地址。之后就可以ping通了。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

果果小师弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值