一、硬件介绍
- W5500 芯片是一款集成全硬件 TCP/IP 协议栈的嵌入式以太网控制器,W5500内嵌的8个独立硬件 Socket 可以进行8路独立通信,该8路Socket的通信效率互不影响,可以通过操作Socket以实现网络的通信。
W5500 最主要的几个引脚对应开发板的SPI引脚
- MISO:(Master Input Slave Output)主机输入从机输出
- MOSI:(Master Output Slave Input)主机输出从机输入
- SCLK:(Serial Clock)时钟信号,由主设备产生
- SCS: (Chip Select)从设备使能信号,由主设备控制
- RSTn: 复位引脚
- INTn:中断引脚
STM32 SPI配置(这里使用的是STM32F103CBT6的SPI1)
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
二、网络环境
本实验是通过交叉线(一端568A,一端568B)将开发板与电脑互连,并用网络助手监测TCP的连接情况。此次例程是需要注意的是要将电脑配置为固定的ip地址。配置过程如下图所示
-
打开网络连接设置,更改适配器 -
打开属性 -
双击Internet协议版本4 -
更改IP地址为固定地址
打开网络状态调试助手,则直接搜到本地IP地址,创建一个TCP Server。 网络调试助手(点击直接下载)
三、W5500的官方驱动库提供的Socket API
本文只介绍TCP客户端开发中需要用到的代码,代码实现在:socket.c 以及socket.h 中
1. socket
功能:初始化socket并打开对应的socket
参数说明:
- sn:所需要打开的socket
- protocol:协议类型
- port:相应的端口号
- flag:特殊的socket模式
uint8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
{
uint8_t ret;
if (
((protocol&0x0F) == Sn_MR_TCP) ||
((protocol&0x0F) == Sn_MR_UDP) ||
((protocol&0x0F) == Sn_MR_IPRAW) ||
((protocol&0x0F) == Sn_MR_MACRAW) ||
((protocol&0x0F) == Sn_MR_PPPOE)
)
{
close(sn);
IINCHIP_WRITE(Sn_MR(sn) ,protocol | flag);
if (port != 0) {
IINCHIP_WRITE( Sn_PORT0(sn) ,(uint8_t)((port & 0xff00) >> 8));
IINCHIP_WRITE( Sn_PORT1(sn) ,(uint8_t)(port & 0x00ff));
} else {
local_port++;
IINCHIP_WRITE(Sn_PORT0(sn) ,(uint8_t)((local_port & 0xff00) >> 8));
IINCHIP_WRITE(Sn_PORT1(sn) ,(uint8_t)(local_port & 0x00ff));
}
IINCHIP_WRITE( Sn_CR(sn) ,Sn_CR_OPEN);
while( IINCHIP_READ(Sn_CR(sn)) )
;
ret = 1;
}
else
{
ret = 0;
}
return ret;
}
2. connect
功能: 客户端模式下为通道建立连接服务器。这个函数一直等待,直到连接建立。
参数说明:
- sn:socket编号
- addr:目标IP地址(需要连接的服务器IP地址)
- port:目标端口(服务器端口)
uint8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
{
uint8_t ret;
if
(
((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00)
)
{
ret = 0;
}
else
{
ret = 1;
IINCHIP_WRITE( Sn_DIPR0(sn), addr[0]);
IINCHIP_WRITE( Sn_DIPR1(sn), addr[1]);
IINCHIP_WRITE( Sn_DIPR2(sn), addr[2]);
IINCHIP_WRITE( Sn_DIPR3(sn), addr[3]);
IINCHIP_WRITE( Sn_DPORT0(sn), (uint8_t)((port & 0xff00) >> 8));
IINCHIP_WRITE( Sn_DPORT1(sn), (uint8_t)(port & 0x00ff));
IINCHIP_WRITE( Sn_CR(sn) ,Sn_CR_CONNECT);
while ( IINCHIP_READ(Sn_CR(sn) ) ) ;
while ( IINCHIP_READ(Sn_SR(sn)) != SOCK_SYNSENT )
{
if(IINCHIP_READ(Sn_SR(sn)) == SOCK_ESTABLISHED)
{
break;
}
if (getSn_IR(sn) & Sn_IR_TIMEOUT)
{
IINCHIP_WRITE(Sn_IR(sn), (Sn_IR_TIMEOUT));
ret = 0;
break;
}
}
}
return ret;
}
3. send
功能:用于TCP模式发送数据
参数说明:
- sn:socket编号
- buf:发送数据缓冲区
- len:发送数据缓冲区的大小
uint16_t send(uint8_t sn, const uint16_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
uint16_t freesize=0;
if (len > getIINCHIP_TxMAX(sn))
ret = getIINCHIP_TxMAX(sn);
else ret = len;
do
{
freesize = getSn_TX_FSR(sn);
status = IINCHIP_READ(Sn_SR(sn));
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT))
{
ret = 0;
break;
}
}
while (freesize < ret);
send_data_processing(sn, (uint8_t *)buf, ret);
IINCHIP_WRITE( Sn_CR(sn) ,Sn_CR_SEND);
while( IINCHIP_READ(Sn_CR(sn) ) );
while ( (IINCHIP_READ(Sn_IR(sn) ) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
{
status = IINCHIP_READ(Sn_SR(sn));
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT) )
{
printf("SEND_OK Problem!!\r\n");
close(sn);
return 0;
}
}
IINCHIP_WRITE( Sn_IR(sn) , Sn_IR_SEND_OK);
#ifdef __DEF_IINCHIP_INT__
putISR(sn, getISR(sn) & (~Sn_IR_SEND_OK));
#else
IINCHIP_WRITE( Sn_IR(sn) , Sn_IR_SEND_OK);
#endif
return ret;
}
4. recv
功能:用于TCP模式接收数据
参数说明:
- sn:socket编号
- buf:接收数据缓冲区
- len:接收数据缓冲区的大小
uint16_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
{
uint16_t ret=0;
if ( len > 0 )
{
recv_data_processing(sn, buf, len);
IINCHIP_WRITE( Sn_CR(sn) ,Sn_CR_RECV);
while( IINCHIP_READ(Sn_CR(sn) ));
ret = len;
}
return ret;
}
5. close
功能:关闭socket
参数说明:
void close(uint8_t sn)
{
IINCHIP_WRITE( Sn_CR(sn) ,Sn_CR_CLOSE);
while( IINCHIP_READ(Sn_CR(sn) ) )
;
IINCHIP_WRITE( Sn_IR(sn) , 0xFF);
}
|