您的位置:首页 > 其它

如何移植使用W5500官方提供的最新Socket库

2015-06-01 17:08 555 查看

转载自:http://www.embed-net.com/thread-55-1-1.html

官方提供了W5500的最新驱动库,下载地址如下:

http://wizwiki.net/wiki/doku.php?id=products:w5500:driver

下面简单介绍下如何使用这套库

首先下载库源码,文件目录如下所示:



我们主要用到Ethernet文件夹下面的文件,将这些文件加入到自己的工程中,然后编译,若编译出现类似于如下错误

..\User\Ethernet\wizchip_conf.c(113): error:#29: expected an expression

.id= _WIZCHIP_ID_,

..\User\Ethernet\wizchip_conf.c(114): error:#29: expected an expression

.if_mode = _WIZCHIP_IO_MODE_,

..\User\Ethernet\wizchip_conf.c(115): error:#29: expected an expression

.CRIS._enter = wizchip_cris_enter,

..\User\Ethernet\wizchip_conf.c(116): error:#29: expected an expression

.CRIS._exit= wizchip_cris_exit,

..\User\Ethernet\wizchip_conf.c(117): error:#29: expected an expression

.CS._select= wizchip_cs_select,

..\User\Ethernet\wizchip_conf.c(118): error:#29: expected an expression

.CS._deselect= wizchip_cs_deselect,

..\User\Ethernet\wizchip_conf.c(119): error:#29: expected an expression

.IF.BUS._read_byte = wizchip_bus_readbyte,

..\User\Ethernet\wizchip_conf.c(120): error:#29: expected an expression

.IF.BUS._write_byte= wizchip_bus_writebyte

..\User\Ethernet\wizchip_conf.c(123): warning:#12-D: parsing restarts here after previous syntax error

};

..\User\Ethernet\wizchip_conf.c: 1 warning, 8 errors

则需要根据自己的编译器做下设置,keil MDK设置如下所示:



主要原因是Keil MDK默认设置不支持按照结构体名称初始化结构体的原因导致。

W5500和MCU是通过SPI接口通信的,库是利用如下结构体中的相关函数指针实现SPI通信和其他功能。

_WIZCHIPWIZCHIP =

{

.id= _WIZCHIP_ID_,

.if_mode = _WIZCHIP_IO_MODE_,

.CRIS._enter = wizchip_cris_enter,

.CRIS._exit= wizchip_cris_exit,

.CS._select= wizchip_cs_select,

.CS._deselect= wizchip_cs_deselect,

.IF.BUS._read_byte = wizchip_bus_readbyte,

.IF.BUS._write_byte= wizchip_bus_writebyte

//.IF.SPI._read_byte = wizchip_spi_readbyte,

//.IF.SPI._write_byte= wizchip_spi_writebyte

};


根据函数名字和库中的注释,我们这里也对要实现的函数做个简单的说明

wizchip_cris_enter :进入临界区的函数,可以不管

wizchip_cris_exit :退出临界区的函数,也可以不管

wizchip_cs_select :输出有效片选信号的函数,也就是控制CS输出低电平的函数,必须实现

wizchip_cs_deselect :控制CS输出高电平的函数,必须实现

wizchip_bus_readbyte :SPI总线读取一字节数据函数,必须实现

wizchip_bus_writebyte :SPI总线写一字节数据函数,必须实现根据以上可知,只要实现了SPI的基本操作,移植基本完成,是不是很简单

下面我们就新建一个spi.c的文件来实现这几个函数,当然这些函数名字可以不和这个结构体里面的函数名字一样,到时候可以调用相关的函数注册下即可

/**

******************************************************************************

*@filespi.c

*$Author: 飞鸿踏雪 $

*$Revision: 17 $

*$Date:: 2014-10-25 11:16:48 +0800 #$

*@brief SPI驱动函数实现.

******************************************************************************

*@attention

*

*<h3><center>© Copyright 2009-2012, EmbedNet</center>

*<center><a href="http:\\www.embed-net.com">http://www.embed-net.com</a></center>

*<center>All Rights Reserved</center></h3>

*

******************************************************************************

*/

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

#include "main.h"

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

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

/*Private macro -------------------------------------------------------------*/

/*Private variables ---------------------------------------------------------*/

/*Private function prototypes -----------------------------------------------*/

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


/**

*@brief使能SPI时钟

*@retval None

*/

static
void

SPI_RCC_Configuration(
void
)

{

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);

}

/**

*@brief配置指定SPI的引脚

*@retval None

*/

static
void

SPI_GPIO_Configuration(
void
)

{

GPIO_InitTypeDef GPIO_InitStruct;

//PA4->CS,PA5->SCK,PA6->MISO,PA7->MOSI

GPIO_InitStruct.GPIO_Pin =GPIO_Pin_5 | GPIO_Pin_6|GPIO_Pin_7;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStruct);

//初始化片选输出引脚

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_SetBits(GPIOA,GPIO_Pin_4);

}

/**

*@brief根据外部SPI设备配置SPI相关参数

*@retval None

*/

void

SPI_Configuration(
void
)

{

SPI_InitTypeDef SPI_InitStruct;


SPI_RCC_Configuration();


SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;

SPI_InitStruct.SPI_Direction= SPI_Direction_2Lines_FullDuplex;

SPI_InitStruct.SPI_Mode = SPI_Mode_Master;

SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;

SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;

SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;

SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStruct.SPI_CRCPolynomial = 7;

SPI_Init(SPI1,&SPI_InitStruct);


SPI_GPIO_Configuration();


SPI_SSOutputCmd(SPI1, ENABLE);

SPI_Cmd(SPI1, ENABLE);

}

/**

*@brief写1字节数据到SPI总线

*@paramTxData 写到总线的数据

*@retval None

*/

void
SPI_WriteByte(uint8_t TxData)

{

while
((SPI1->SR&SPI_I2S_FLAG_TXE)==0);
//等待发送区空

SPI1->DR=TxData;
//发送一个byte

while
((SPI1->SR&SPI_I2S_FLAG_RXNE)==0);
//等待接收完一个byte

SPI1->DR;

}

/**

*@brief从SPI总线读取1字节数据

*@retval 读到的数据

*/

uint8_t SPI_ReadByte(
void
)

{

while
((SPI1->SR&SPI_I2S_FLAG_TXE)==0);
//等待发送区空

SPI1->DR=0xFF;
//发送一个空数据产生输入数据的时钟

while
((SPI1->SR&SPI_I2S_FLAG_RXNE)==0);
//等待接收完一个byte

return

SPI1->DR;

}

/**

*@brief进入临界区

*@retval None

*/

void

SPI_CrisEnter(
void
)

{

__set_PRIMASK(1);

}

/**

*@brief退出临界区

*@retval None

*/

void

SPI_CrisExit(
void
)

{

__set_PRIMASK(0);

}


/**

*@brief片选信号输出低电平

*@retval None

*/

void

SPI_CS_Select(
void
)

{

GPIO_ResetBits(GPIOA,GPIO_Pin_4);

}

/**

*@brief片选信号输出高电平

*@retval None

*/

void

SPI_CS_Deselect(
void
)

{

GPIO_SetBits(GPIOA,GPIO_Pin_4);

}

/*********************************END OF FILE**********************************/


到这里,移植基本上完成。

但是这些SPI的接口函数如何跟这套库衔接呢?不用怕,库提供有这样的函数来注册,只要在主函数中调用下就可以了,具体程序如下
// First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP

/*Critical section callback */

reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);
//注册临界区函数

/*Chip selection call back */

#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_

reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_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(SPI_ReadByte, SPI_WriteByte);
//注册读写函数


到这里,移植工程基本完成,下面我们就将官方提供的一个loopback的测试程序移植到我们自己的工程中来,基本上也没做什么修改,下面是测试工程用到的几个测试函数

/**

*@briefIntialize the network information to be used in WIZCHIP

*@retval None

*/

void

network_init(
void
)

{

 
uint8_t tmpstr[6];

ctlnetwork(CN_SET_NETINFO, (
void
*)&gWIZNETINFO);

ctlnetwork(CN_GET_NETINFO, (
void
*)&gWIZNETINFO);


// Display Network Information

ctlwizchip(CW_GET_ID,(
void
*)tmpstr);

printf
(
"\r\n=== %s NET CONF ===\r\n"
,(
char
*)tmpstr);

printf
(
"MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"
,gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],

gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);

printf
(
"SIP: %d.%d.%d.%d\r\n"
, gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);

printf
(
"GAR: %d.%d.%d.%d\r\n"
, gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]);

printf
(
"SUB: %d.%d.%d.%d\r\n"
, gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);

printf
(
"DNS: %d.%d.%d.%d\r\n"
, gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);

printf
(
"======================\r\n"
);

}


/**

*@briefLoopback Test Example Code using ioLibrary_BSD

*@retval None

*/

int32_t loopback_tcps(uint8_t sn, uint8_t*buf, uint16_t port)

{

 
int32_t ret;

 
uint16_t size = 0, sentsize=0;

 
switch
(getSn_SR(sn))

 
{

case

SOCK_ESTABLISHED :

 
if
(getSn_IR(sn) & Sn_IR_CON)

 
{

printf
(
"%d:Connected\r\n"
,sn);

setSn_IR(sn,Sn_IR_CON);

 
}

 
if
((size = getSn_RX_RSR(sn)) > 0)

 
{

if
(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;

ret = recv(sn,buf,size);

if
(ret <= 0)
return
ret;

sentsize = 0;

while
(size != sentsize)

{

 
ret = send(sn,buf+sentsize,size-sentsize);

 
if
(ret < 0)

 
{

close(sn);

return

ret;

 
}

 
sentsize += ret;
// Don't care SOCKERR_BUSY, because it is zero.

}

 
}

 
break
;

case

SOCK_CLOSE_WAIT :

 
printf
(
"%d:CloseWait\r\n"
,sn);

 
if
((ret=disconnect(sn)) != SOCK_OK)
return
ret;

 
printf
(
"%d:Closed\r\n"
,sn);

 
break
;

case

SOCK_INIT :

printf
(
"%d:Listen, port [%d]\r\n"
,sn, port);

 
if
( (ret = listen(sn)) != SOCK_OK)
return
ret;

 
break
;

case

SOCK_CLOSED:

 
printf
(
"%d:LBTStart\r\n"
,sn);

 
if
((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)

return

ret;

 
printf
(
"%d:Opened\r\n"
,sn);

 
break
;

default
:

 
break
;

 
}

 
return

1;

}


/**

*@briefLoopback Test Example Code using ioLibrary_BSD

*@retval None

*/

int32_t loopback_udps(uint8_t sn, uint8_t*buf, uint16_t port)

{

 
int32_tret;

 
uint16_t size, sentsize;

 
uint8_tdestip[4];

 
uint16_t destport;

 
//uint8_tpackinfo = 0;

 
switch
(getSn_SR(sn))

 
{

case

SOCK_UDP :

 
if
((size = getSn_RX_RSR(sn)) > 0)

 
{

if
(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;

ret = recvfrom(sn,buf,size,destip,(uint16_t*)&destport);

if
(ret <= 0)

{

 
printf
(
"%d: recvfrom error. %ld\r\n"
,sn,ret);

 
return

ret;

}

size = (uint16_t) ret;

sentsize = 0;

while
(sentsize != size)

{

 
ret = sendto(sn,buf+sentsize,size-sentsize,destip,destport);

 
if
(ret < 0)

 
{

printf
(
"%d: sendto error. %ld\r\n"
,sn,ret);

return

ret;

 
}

 
sentsize += ret;
// Don't care SOCKERR_BUSY, because it is zero.

}

 
}

 
break
;

case

SOCK_CLOSED:

 
printf
(
"%d:LBUStart\r\n"
,sn);

 
if
((ret=socket(sn,Sn_MR_UDP,port,0x00)) != sn)

return

ret;

 
printf
(
"%d:Opened, port [%d]\r\n"
,sn, port);

 
break
;

default

:

 
break
;

 
}

 
return

1;

}


/**

*@briefLoopback Test Example Code using ioLibrary_BSD

*@retval None

*/

void

platform_init(
void
)

{

SystemInit();
//系统时钟初始化

USART_Configuration();
//串口1初始化

printf
(
"\x0c"
);
printf
(
"\x0c"
);
//超级终端清屏

printf
(
"\033[1;40;32m"
);
//设置超级终端背景为黑色,字符为绿色

printf
(
"\r\n*******************************************************************************"
);

printf
(
"\r\n************************Copyright 2009-2014, EmbedNet ************************"
);

printf
(
"\r\n***************************http://www.embed-net.com **************************"
);

printf
(
"\r\n*****************************All Rights Reserved *****************************"
);

printf
(
"\r\n*******************************************************************************"
);

printf
(
"\r\n"
);

//Config SPI

SPI_Configuration();

//延时初始化

delay_init();

}

我们自己在工程中加了串口打印程序,程序运行后串口输出信息如下:



我们ping下程序里面的IP试试



能ping通,看来没什么大问题了

STM32工程源码下载:http://www.embed-net.com/thread-55-1-1.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: