STM32配置W5500

一、下载W5500官方提供的驱动库:
ioLibrary_Driver-master

二、库文件分析

ioLibrary_Driver-master
	Application	//官方提供的测试程序
		loopback
		multicast
	Ethernet	//底层配置
		W5100
		W5100S
		W5200
		W5300
		W5500
	Internet	//网络应用层
		DHCP
		DNS
		FTPClient
		FTPServer
		httpServer
		MQTT
		SNMP
		SNTP
		TFTP

三、开始配置
打开ioLibrary_Driver-master\Ethernet文件夹下面的wizchip_conf.c文件。
官方提供了接口,待用户补充:

	void 	wizchip_cris_enter(void)           {}
	void 	wizchip_cris_exit(void)          {}
	void 	wizchip_cs_select(void)            {}
	void 	wizchip_cs_deselect(void)          {}
	iodata_t wizchip_bus_readdata(uint32_t AddrSel) { return * ((volatile iodata_t *)((ptrdiff_t) AddrSel)); }
	void 	wizchip_bus_writedata(uint32_t AddrSel, iodata_t wb)  { *((volatile iodata_t*)((ptrdiff_t)AddrSel)) = wb; }
	uint8_t wizchip_spi_readbyte(void)        {return 0;}
	void 	wizchip_spi_writebyte(uint8_t wb) {}
	void 	wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) 	{}
	void 	wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {}

这里并不是每个函数都要填充,也不是一定要使用这些函数。这些函数存在的意义只是提供了一个模型,真正将我们自己的硬件配置和他们的库相连接的地方是在底下的注册函数:

//注册进入/退出临界区函数
void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
//注册SPI片选(CS) 选择/去选择函数
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
//注册总线 读/写 函数
void reg_wizchip_bus_cbfunc(iodata_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb))
//注册 SPI 按字节 读/写 函数
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
//注册 SPI 按长度 读/写函数
void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len))

其中我们只需要关心三个函数:临界区、片选、SPI按字节读写。
因为程序没有跑系统,不需要临界保护,所以这里保持默认即可,无需修改。:
片选配置:

//void 	wizchip_cs_select(void)            {};
void wizchip_cs_select(void)            
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}
//void 	wizchip_cs_deselect(void)          {};
void wizchip_cs_deselect(void)          
{
	GPIO_SetBits(GPIOB, GPIO_Pin_12);
}

SPI读写配置:

uint8_t wizchip_spi_readbyte(void)
{
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
	SPI_I2S_SendData(SPI2, 0xFF);
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
	return SPI_I2S_ReceiveData(SPI2);
}
//void 	wizchip_spi_writebyte(uint8_t wb) {};
void 	wizchip_spi_writebyte(uint8_t wb) 
{
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
	SPI_I2S_SendData(SPI2, wb);
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
	return SPI_I2S_ReceiveData(SPI2);
}

注册上面的三个函数(只需要三个):

void user_reg_wizchip(void)
{
  // First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP
     /* Critical section callback */
     reg_wizchip_cris_cbfunc(wizchip_cris_enter, wizchip_cris_exit);    //注册临界区函数
     /* Chip selection call back */
#if   _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_
     reg_wizchip_cs_cbfunc(wizchip_cs_select, wizchip_cs_deselect); //注册SPI片选信号函数
#elif _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_FDM_
     reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);   // CS must be tried with LOW.
#else
    #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_
       #error "Unknown _WIZCHIP_IO_MODE_"
    #else
       reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
    #endif
#endif
     /* SPI Read & Write callback function */
     reg_wizchip_spi_cbfunc(wizchip_spi_readbyte, wizchip_spi_writebyte);     //注册读写函数
}

然后主程序就可以调用了:

	uint8_t mac[6]={0x00,0x08,0xdc,0x11,0x11,0x11};
	uint8_t lip[4]={192,168,1,150};
	uint8_t sub[4]={255,255,255,0};
	uint8_t gw[4]={192,168,1,1};
	uint8_t dns[4]={8,8,8,8};
	wiz_NetInfo gWIZNETINFO;
	memcpy(gWIZNETINFO.ip, lip, 4);
	memcpy(gWIZNETINFO.mac, mac, 6);
	memcpy(gWIZNETINFO.gw, gw, 4);
	memcpy(gWIZNETINFO.sn, sub, 4);
	memcpy(gWIZNETINFO.dns, dns, 4);
	W5500_HalInit();
	delay_ms(100); //必须要有延时
	user_reg_wizchip();
	wizchip_sw_reset();
	ctlwizchip(CW_GET_ID,( void *)tmpstr);
	ctlnetwork(CN_SET_NETINFO, ( void *)&gWIZNETINFO);
	while(1);

至此,可以使用cmd工具ping通了。

C:\Users\lenovo>ping 192.168.1.150

正在 Ping 192.168.1.150 具有 32 字节的数据:
来自 192.168.1.150 的回复: 字节=32 时间<1ms TTL=128
来自 192.168.1.150 的回复: 字节=32 时间<1ms TTL=128
来自 192.168.1.150 的回复: 字节=32 时间<1ms TTL=128
来自 192.168.1.150 的回复: 字节=32 时间<1ms TTL=128

192.168.1.150 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 0ms,最长 = 0ms,平均 = 0ms

注意:W5500 socket使用resv接口时,注意该接口是无限阻塞的,如果调用了该接口,会一直等待接收到数据才会返回。
官方实现:

int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
{
	........
	while(1)
    {
        recvsize = getSn_RX_RSR(sn);
        tmp = getSn_SR(sn);
        if (tmp != SOCK_ESTABLISHED)
        {
           if(tmp == SOCK_CLOSE_WAIT)
           {
              if(recvsize != 0) break;
              else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
              {
                 close(sn);
                 return SOCKERR_SOCKSTATUS;
              }
           }
           else
           {
              close(sn);
              return SOCKERR_SOCKSTATUS;
           }
        }
        if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
        if(recvsize != 0) break;
     };
}

为了防止影响其他程序执行,这里修改为:

	.....
	if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
    if(recvsize != 0) break;
    else return 0;

然后再调用的地方增加超时检测:

int32_t Socket_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
{
	uint32_t index=0;
	int32_t len_recv=0;
	do
	{
		delay_ms(1);
		index = recv(0, (uint8_t *)(buf+len_recv), (len-len_recv) );
		if(index>0)
			len_recv += index;

		if(--timeout_ms < 1)
		{
			len_recv = 0;
			return (int32_t)0;
		}
	}while(len_recv<len);
	return (int32_t)len_recv;
}
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值