标题：w5300
特性：
l 支持软、硬件混合TCP/IP协议： TCP, UDP, ICMP, IGMP, IPv4, ARP, PPPoE, Ethernet；
l 支持8个独立的端口（sockets）同时连接；
l 网络数据传输，速率可达到80Mbps；
l 支持ADSL连接 (支持PPPOE协议，带PAP/CHAP验证)；
l 内部128K字节存储器作TX/RX缓存； 
l 根据端口通信数据吞吐量动态调整内部TX/RX存储器分配；
l 内嵌10BaseT/100BaseTX以太网物理层，支持自动应答（全双工/半双工模式）；
I 可选TX1:1 RX1:1 网络变压器接口YL18-2050S,YT37-1107S及YL2J011D，YL2J201A
l 支持自动极性变换（MDI/MDIX）；
l 支持8/16位数据总线；
l 0.18μm CMOS工艺；
l 3.3V工作电压，I/O口可承受5V电压,内部带1.8V电压调整器；
l LQFP-100，14x14mm无铅封装。
模块：
PLL 锁相环将25MHz的时钟源经过6倍频，建立150MHz的时钟信号。150MHz的时钟用于内部单元的运行，如
TCP/IP内核、主机接口管理和寄存器管理。锁相环在复位后锁定并提供稳定的时钟信号。电源调节系统电源调节系统通过3.3v的输入建立1.8v/150mA的输出电压。电源调节系统为W5300的内核提供电源。
因此不需要其它电源调节器。为了使1.8v的电源更稳定，建议增加电容滤波。主机接口管理它根据数据总线的宽度或主机接口模式，检测主机总线信号，管理读写操作。寄存器管理它管理模式寄存器、通用（COMMON）寄存器和SOCKET（端口）寄存器。存储器管理它管理内部128K字节的数据存储器。由主机分配每个端口的TX/RX存储器。主机可以通过每个
SOCKET的FIFO寄存器访问TX/RX存储器。128K字节TX/RX DPRAM这是128K字节通信数据存储器，组成16个8K字节的DPRAM (双端口RAM)。可以由主机灵活分配给
每个SOCKET。MII接口管理它管理MII接口，根据TEST_MODE[3:0]的配置，MII接口可以在内部PHY和外部PHY（第三方PHY）
之间切换。内部以太网PHYW5300内部集成了10BaseT/100BaseTX的以太网PHY。PHY支持半双工/全双工自动握手和
MDI/MDIX自动检查。它还支持6种网络指示的LED输出，如LINK状态、速度和双工状态。TCP/IP内核TCP/IP内核是完全基于WIZnet网络协议处理技术进行硬件逻辑化。
- 802.3以太网MAC（介质访问控制）    

功能描述
W5300可以通过寄存器的设置使Internet的连接变得非常简单。在本章将学习怎样初始化W5300，通
过学习一些代码，怎样根据协议类型（TCP、UDP、IPRAW和MACRAW）实现网络通信。
初始化
W5300的初始化分三个步骤：主机接口设置，网络信息设置和内部TX/RX存储器的分配。
第1步：设置主机接口
1. 设置数据总线宽度，主机接口模式和时序（参考MR寄存器）
2. 设置主机中断（参考IMR）
第2步：设置网络信息
1. 设置数据通信的基本网络信息（参考：SHAR、GAS、SBUR和SIPR）
2. 设置重复发送的时间间隔和重复发送的次数，用于数据包发送失败时的重复发送（参考RTR和
RCR）
本机硬件地址通过SHAR设置，这是一个以太网设备的唯一的硬件地址（以太网的MAC地址），应用
于以太网的MAC层
由IEEE分配和管理MAC地址。生产厂商需要从IEEE申请网络设备的MAC地址。
第3步：分配SOCKETn的内部TX/RX存储器空间
1. 定义内部TX/RX存储器大小（参考MYTPER）
2. 定义SOCKETn的TX/RX存储器大小（参考TMR和RMSR）
W5300内部包含16个8K字节的存储单元。这些存储单元依次映射在128K字节的存储器空间。128K存
储器分为发送存储器（TX）和接收存储器（RX）。内部TX和RX存储器以8K字节为单元分布在128K字节
空间。内部TX/RX存储器可以在0~64K字节空间以1K字节为单元从新分配给每个SOCKET。  
当第3步初始化设置完成后，就可以使用W5300通过以太网传输数据了。这时，W5300可以响应Ping
请求（自动Ping响应）。
数据通信
完成初始化设置以后，W5300可以以TCP、UDP、IPRAW或MACRAW的方式打开SOCKET发送或接
收数据。W5300支持8个SOCKET同时且独立地工作。在本章将描述每种通信方式的工作方法。
1 TCPTCP是一种连接通信的协议，在TCP模式，首先要根据IP地址和端口号与对端建立SOCKET连接。通
过连接的SOCKET发送和接收数据。
建立SOCKET的连接有“TCP服务器”和“TCP客户端”之分。区分它们的方法是谁首先发送连接请
求（SYS数据包）。“TCP服务器”等待对端的连接请求，当收到连接请求时建立SOCKET连接（被动打
开）。“TCP客户端”主动发出连接请求，与对端建立连接（主动打开）。 
SOCKET初始化
为了实现TCP通信，需要对SOCKET进行初始化设置并打开SOCKET。为了打开SOCKET，选择其中
的一个SOCKET（被选择的SOCKET称之为SOCKETn），通过Sn_MR(P3:P0)和Sn_PORTR分别设置通
信协议和本机端口号（在TCP服务器模式，称之为侦听端口号），然后执行OPEN命令。执行完OPEN命
令后，如果Sn_SSR改变为SOCK_INIT，则SOCKET的初始化设置完成。
在TCP服务器和TCP客户端模式，SOCKET初始化的过程都是相同的。下面的方法是将SOCKET初始
化为TCP模式。
{
START:
Sn_MR = 0x0001; /* sets TCP mode */
Sn_PORTR = source_port; /* sets source port number */
Sn_CR = OPEN; /* sets OPEN command */
/* wait until Sn_SSR is changed to SOCK_INIT */
if (Sn_SSR != SOCK_INIT) Sn_CR = CLOSE; goto START;
}
如果接收到对端的数据字节数为偶数，Sn_MR(ALIGN)置‘1’。当Sn_MR(ALIGN)=1时，W5300不
需要增加TCP模式的PACKET-INFO，而只将数据保存在SOCKETn的内部RX存储器。这样将减少主机对
SOCKET_INFO的额外处理，提高系统性能。（在前面的代码中，Sn_MR=0x0101可能会被Sn_MR=0x0001
取代）
侦听
运行LISTEN命令将W5300设置为TCP服务器模式
{
/* listen SOCKET */
Sn_CR = LISTEN;
/* wait until Sn_SSR is changed to SOCK_LISTEN */
If (Sn_SSR != SOCK_LISTEN) Sn_CR = CLOSE; goto START;
}
建立连接？
当Sn_SSR改变为SOCK_LISTEN状态时，如果收到SYN数据包，那么Sn_SSR将改变为
SOCK_SYNRECV。发送了SYN/ACK数据包后，SOCKETn就建立了连接。SOCKETn建立连接以后就可
以进行数据通信。有两种方法可以检验是否建立SOCKETn的连接。
第1种方法
{
if (Sn_IR(CON) == ‘1’) Sn_IR(CON) = ‘1’; goto ESTABLISHED stage;
/* In this case, if the interrupt of SOCKETn is activated, interrupt occurs. Refer to IR, IMR
Sn_IMR and Sn_IR. */
} 
第二种方法
{
if (Sn_SSR == SOCK_ESTABLISHED) goto ESTABLISHED stage;
}
建立连接：接收到数据？
检查是否接收到对端发送来的数据。
第1种方法
{
if (Sn_IR(RECV) == ‘1’) Sn_IR(RECV) = ‘1’; goto Receiving Process stage;
/* In this case, if the interrupt of SOCKETn is activated, interrupt occurs. Refer to IR, IMR
Sn_IMR and Sn_IR. */
}
第2种方法
{
if (Sn_RX_RSR != 0x00000000) goto Receiving Process stage;
}
第1种方法，当SOCKETn接收到数据包时，Sn_IR(RECV)将置‘1’。这时如果主机还没有处理上次
接收数据包的Sn_IR(RECV)，而W5300又收到下一次的数据包，主机保持前一次的Sn_IR(RECV)，不能
识别下一次数据包的Sn_IR(RECV)，因此，如果主机没有能力处理所有数据包的Sn_IR(RECV)，建议不
采用这种方法。
建立连接：接收数据处理
当Sn_MR(ALIGN)=0时，数据包中包含PACKET-INFO和数据的数据。在Sn_ME(ALIGN)=1时，TCP
数据只有数据包而没有PACKET-INFO。
在TCP模式，如果对端发送的数据的大小超过SOCKETn的RX存储器的剩余空间，那么W5300将不能
接收数据，这时的W5300将继续保持连接，并等待RX存储器的剩余空间大于数据长度。
{
/* first, check Sn_MR(ALIGN) */
if (Sn_MR(ALIGN) == ‘0’)
{
pack_size = Sn_RX_FIFOR; /* extract size of DATA packet from internal RX memory */
}
else
{
pack_size = Sn_RX_RSR; /* check the total received data size */
}
/* calculate the read count of Sn_RX_FIFOR */
if (pack_size is odd ?) read_cnt = (pack_size + 1) / 2;
read_cnt = pack_size / 2;
/* extract DATA packet from internal RX memory */
for( i = 0; i < read_cnt; i++)
{
data_buf[i] = Sn_RX_FIFOR; /* data_buf is array of 16bit */
}
/* set RECV command */
Sn_CR = RECV;
}
注意：当SOCKETn只用于接收数据而不发送数据时，主机不能快速接收处理数据将导致使内部RX存
储器溢出。
在这种情况下，即使W5300的窗口尺寸（接收数据的最大尺寸）不为0，对端误以为窗口尺寸为0而不再发送数据，等待窗口尺寸增加。这样就会降低W5300接收数据的性能。为了解决这个问题，主机首先处理内部RX存储器接收的数据，同时通知对端，W5300的窗口尺寸增加了已经接收数据的大小。针对上面代码，在RECV命令之后增加以下的代码。
/* set RECV command */
Sn_CR = RECV;
/* Add the code that notifies the update of window size to the peer */
/* check the received data process to finish or not */
if(Sn_RX_RSR == 0) /* send the window-update packet when the window size is full */
{ /* Sn_RX_RSR can be compared with another value instead of „0‟, according to the host
performance of receiving data */
Sn_TX_WRSR = 0x00000001; /* set Dummy Data size to Sn_TX_WRSR */
Sn_CR = SEND; /* set SEND command */
while(Sn_CR != 0x00); /* check SEND command completion */
while(Sn_IR(SENDOK) == 0); /* wait for SEND OK */
Sn_IR(SENDOK) =1; /* Clear SENDOK bit */
}
建立连接：发送数据？/发送处理    
将数据通过Sn_TX_FIFOR写入到内部TX存储器后，W5300将试着把数据发送到对端。发送数据的大
小不能比分配给该SOCKETn的内部TX存储器空间大。如果发送数据的尺寸比MSS大，W5300将自动根据
MSS分片，然后再发送。
为了下一次数据的发送，主机必须检查上次SEND命令是否执行完毕。如果上一次的SEND命令还没
有执行完而又开始下一次的SEND命令，将可能产生各种各样的错误。数据越大，执行SEND命令所需要
的时间就会越长。所以要想提高发送效率，适当将数据分为合适的大小发送。
{
/* first, get the free TX memory size */
FREESIZE:
get_free_size = Sn_TX_FSR;
if (Sn_SSR != SOCK_ESTABLISHED && Sn_SSR != SOCK_CLOSE_WAIT) goto CLOSED
state;
if (get_free_size < send_size) goto FREESIZE;
/* calculate the write count of Sn_TX_FIFOR */
if (send_size is odd ?) write_cnt = (send_size + 1) / 2;
else write_cnt = send_size / 2;
/* copy data to internal TX memory */
for (i = 0; i < write_cnt; i++)
{
Sn_TX_FIFOR = data_buf[i]; /* data_buf is array of 16bit */
}
/* check previous SEND command completion */
if (is first send ?) ; /* skip check Sn_IR(SENDOK) */
else
{
while(Sn_IR(SENDOK)==‘0’)
{
if(Sn_SSR == SOCK_CLOSED) goto CLOSED state; /* check connection establishment */
}
Sn_IR(SENDOK) = ‘1’; /* clear previous interrupt of SEND completion */
}
/* sets transmission data size to Sn_TX_WRSR */
Sn_TX_WRSR = send_size;
/* set SEND command */
Sn_CR = SEND;
}
建立连接：接收到FIN
它检查是否接收到断开连接的请求（FIN数据包）。检查如下：
第1种方法
{
if (Sn_IR(DISCON) == ‘1’) Sn_IR(DISCON)=‘1’; goto CLOSED stage;
/* In this case, if the interrupt of SOCKETn is activated, interrupt occurs. Refer to IR, IMR
Sn_IMR and Sn_IR. */
}
第2种方法
{
if (Sn_SSR == SOCK_CLOSE_WAIT) goto CLOSED stage;
}
建立连接：断开连接？/断开连接处理
如果不再需要进行数据通信，或收到FIN数据包，那么SOCKET的连接应该断开。
{
/* set DISCON command */
Sn_CR = DISCON;
}
建立连接：关闭端口？
它检查SOCKETn是否通过DISCON或CLOSE命令断开连接或关闭端口。
第1种方法
{
if (Sn_IR(DISCON) == ‘1’) goto CLOSED stage;
/* In this case, if the interrupt of SOCKETn is activated, interrupt occurs. Refer to IR, IMR
Sn_IMR and Sn_IR. */
}
第2种方法
{
if (Sn_SSR == SOCK_CLOSED) goto CLOSED stage;
}
建立连接：超时
超时可能发生在TCP数据包传输过程中，如连接请求（SYN数据包）或其响应数据包（SYN/ACK数
据包）、数据（DATA数据包）或其响应数据包（DATA/ACK数据包）、断开连接请求（FIN数据包）或其
响应数据包（FIN/ACK数据包）等等。如果以上的数据包在RTR和RCR设定的时间内没有发送出去，那么
将产生TCP超时，且Sn_SSR将改变为SOCK_CLOSED状态。
TCP超时检查如下：
第1种方法：
{
if (Sn_IR(TIMEOUT bit) == ‘1’) Sn_IR(TIMEOUT)=‘1’; goto CLOSED stage;
/* In this case, if the interrupt of SOCKETn is activated, interrupt occurs. Refer to IR, IMR
Sn_IMR and Sn_IR. */
}
第2种方法：
{
if (Sn_SSR == SOCK_CLOSED) goto CLOSED stage;
}
SOCKET关闭
SOCKETn经过断开连接处理或由于超时而断开连接，它用于关闭断开连接的SOCKETn。主机也可以不进
行断开连接处理而直接关闭SOCKETn。
{
/* clear remained interrupts */
Sn_IR = 0x00FF;
IR(n) = ‘1’;
/* set CLOSE command */
Sn_CR = CLOSE;
}2 TCP客户端它发送连接请求（SYN数据包）到对端。在与对端SOCKET建立连接的过程中可能会出现ARP超时，
或TCP连接超时。
{
Sn_DIPR = server_ip; /* set TCP SERVER IP address*/
Sn_DPORTR = server_port; /* set TCP SERVER listen port number*/
Sn_CR = CONNECT; /* set CONNECT command */
}