STM32F107——W5500网络通信
扫描二维码
随时随地手机看文章
#ifndef _W5500_QUEUE_H_
#define _W5500_QUEUE_H_
#include "type.h"
#define W5500_FRAME_SIZE 2048
#define W5500_RECV_QUEUE_SIZE 20
typedef enum
{
W5500_FAILURE = 0,
W5500_OK = 1,
} w5500_queue_status_t;
typedef __packed struct
{
uint8_t data[W5500_FRAME_SIZE];
uint16_t length;
} w5500_frame_t;
typedef struct
{
uint16_t in;
uint16_t out;
uint16_t count;
uint16_t item_size[W5500_RECV_QUEUE_SIZE];
uint8_t data[W5500_RECV_QUEUE_SIZE][W5500_FRAME_SIZE];
} w5500_queue_t;
extern w5500_queue_t w5500_queue_recv;
void W5500QueueInit(w5500_queue_t *q);
uint8_t W5500QueueWrite(w5500_queue_t *q, w5500_frame_t *data);
uint8_t W5500QueueRead(w5500_queue_t *q, w5500_frame_t *data);
#endif /* _W5500_QUEUE_H_ */#include "w5500_queue.h"
#include#include#include "debug.h"
w5500_queue_t w5500_queue_recv;
void W5500QueueInit(w5500_queue_t *q)
{
int i;
for(i = 0; i < W5500_RECV_QUEUE_SIZE; ++i)
{
memset(q->data[i], 0, W5500_FRAME_SIZE);
}
memset(q->item_size, 0, sizeof(q->item_size));
q->in = 0;
q->out = 0;
q->count = 0;
}
uint8_t W5500QueueWrite(w5500_queue_t *q, w5500_frame_t *frame)
{
if((q->out % W5500_RECV_QUEUE_SIZE == q->in) && (q->count == W5500_RECV_QUEUE_SIZE))
{
return W5500_FAILURE;
}
q->item_size[q->in] = frame->length;
memcpy(q->data[q->in], frame->data, frame->length);
q->in = (q->in + 1) % W5500_RECV_QUEUE_SIZE;
q->count++;
return W5500_OK;
}
uint8_t W5500QueueRead(w5500_queue_t *q, w5500_frame_t *frame)
{
if((q->in == q->out) && (q->count == 0))
{
return W5500_FAILURE;
}
frame->length = q->item_size[q->out];
memcpy(frame->data, q->data[q->out], q->item_size[q->out]);
q->out = (q->out + 1) % W5500_RECV_QUEUE_SIZE;
q->count--;
return W5500_OK;
}#ifndef _W5500_H_ #define _W5500_H_ #include "type.h" #include "debug.h" /***************** Common Register *****************/ #define MR 0x0000 #define RST 0x80 #define WOL 0x20 #define PB 0x10 #define PPP 0x08 #define FARP 0x02 #define GAR 0x0001 #define SUBR 0x0005 #define SHAR 0x0009 #define SIPR 0x000f #define INTLEVEL 0x0013 #define IR 0x0015 #define CONFLICT 0x80 #define UNREACH 0x40 #define PPPOE 0x20 #define MP 0x10 #define IMR 0x0016 #define IM_IR7 0x80 #define IM_IR6 0x40 #define IM_IR5 0x20 #define IM_IR4 0x10 #define SIR 0x0017 #define S7_INT 0x80 #define S6_INT 0x40 #define S5_INT 0x20 #define S4_INT 0x10 #define S3_INT 0x08 #define S2_INT 0x04 #define S1_INT 0x02 #define S0_INT 0x01 #define SIMR 0x0018 #define S7_IMR 0x80 #define S6_IMR 0x40 #define S5_IMR 0x20 #define S4_IMR 0x10 #define S3_IMR 0x08 #define S2_IMR 0x04 #define S1_IMR 0x02 #define S0_IMR 0x01 #define RTR_w5500 0x0019 #define RCR_w5500 0x001b #define PTIMER 0x001c #define PMAGIC 0x001d #define PHA 0x001e #define PSID 0x0024 #define PMRU 0x0026 #define UIPR 0x0028 #define UPORT 0x002c #define PHYCFGR 0x002e #define RST_PHY 0x80 #define OPMODE 0x40 #define DPX 0x04 #define SPD 0x02 #define LINK 0x01 #define VERR 0x0039 /********************* Socket Register *******************/ #define Sn_MR 0x0000 #define MULTI_MFEN 0x80 #define BCASTB 0x40 #define ND_MC_MMB 0x20 #define UCASTB_MIP6B 0x10 #define MR_CLOSE 0x00 #define MR_TCP 0x01 #define MR_UDP 0x02 #define MR_MACRAW 0x04 #define Sn_CR 0x0001 #define OPEN 0x01 #define LISTEN 0x02 #define CONNECT 0x04 #define DISCON 0x08 #define CLOSE 0x10 #define SEND 0x20 #define SEND_MAC 0x21 #define SEND_KEEP 0x22 #define RECV 0x40 #define Sn_IR 0x0002 #define IR_SEND_OK 0x10 #define IR_TIMEOUT 0x08 #define IR_RECV 0x04 #define IR_DISCON 0x02 #define IR_CON 0x01 #define Sn_SR 0x0003 #define SOCK_CLOSED 0x00 #define SOCK_INIT 0x13 #define SOCK_LISTEN 0x14 #define SOCK_ESTABLISHED 0x17 #define SOCK_CLOSE_WAIT 0x1c #define SOCK_UDP 0x22 #define SOCK_MACRAW 0x02 #define SOCK_SYNSEND 0x15 #define SOCK_SYNRECV 0x16 #define SOCK_FIN_WAI 0x18 #define SOCK_CLOSING 0x1a #define SOCK_TIME_WAIT 0x1b #define SOCK_LAST_ACK 0x1d #define Sn_PORT 0x0004 #define Sn_DHAR 0x0006 #define Sn_DIPR 0x000c #define Sn_DPORTR 0x0010 #define Sn_MSSR 0x0012 #define Sn_TOS 0x0015 #define Sn_TTL 0x0016 #define Sn_RXBUF_SIZE 0x001e #define Sn_TXBUF_SIZE 0x001f #define Sn_TX_FSR 0x0020 #define Sn_TX_RD 0x0022 #define Sn_TX_WR 0x0024 #define Sn_RX_RSR 0x0026 #define Sn_RX_RD 0x0028 #define Sn_RX_WR 0x002a #define Sn_IMR 0x002c #define IMR_SENDOK 0x10 #define IMR_TIMEOUT 0x08 #define IMR_RECV 0x04 #define IMR_DISCON 0x02 #define IMR_CON 0x01 #define Sn_FRAG 0x002d #define Sn_KPALVTR 0x002f /*******************************************************************/ /************************ SPI Control Byte *************************/ /*******************************************************************/ /* Operation mode bits */ #define VDM 0x00 #define FDM1 0x01 #define FDM2 0x02 #define FDM4 0x03 /* Read_Write control bit */ #define RWB_READ 0x00 #define RWB_WRITE 0x04 /* Block select bits */ #define COMMON_R 0x00 /* Socket 0 */ #define S0_REG 0x08 #define S0_TX_BUF 0x10 #define S0_RX_BUF 0x18 /* Socket 1 */ #define S1_REG 0x28 #define S1_TX_BUF 0x30 #define S1_RX_BUF 0x38 /* Socket 2 */ #define S2_REG 0x48 #define S2_TX_BUF 0x50 #define S2_RX_BUF 0x58 /* Socket 3 */ #define S3_REG 0x68 #define S3_TX_BUF 0x70 #define S3_RX_BUF 0x78 /* Socket 4 */ #define S4_REG 0x88 #define S4_TX_BUF 0x90 #define S4_RX_BUF 0x98 /* Socket 5 */ #define S5_REG 0xa8 #define S5_TX_BUF 0xb0 #define S5_RX_BUF 0xb8 /* Socket 6 */ #define S6_REG 0xc8 #define S6_TX_BUF 0xd0 #define S6_RX_BUF 0xd8 /* Socket 7 */ #define S7_REG 0xe8 #define S7_TX_BUF 0xf0 #define S7_RX_BUF 0xf8 #define SOCKET_OK 0xff #define SOCKET_FAILURE 0x00 #define S_RX_SIZE 2048 /*定义Socket接收缓冲区的大小,可以根据W5500_RMSR的设置修改 */ #define S_TX_SIZE 2048 /*定义Socket发送缓冲区的大小,可以根据W5500_TMSR的设置修改 */ /***************----- 端口数据缓冲区 -----***************/ extern uint8_t socket_rx_buffer[2048]; //端口接收数据缓冲区 extern uint8_t socket_tx_buffer[2048]; //端口发送数据缓冲区 typedef unsigned char SOCKET; //自定义端口号数据类型 void W5500Init(void); void W5500SocketScan(void); uint16_t W5500SocketRecv(uint8_t *buffer); void W5500SocketSend(uint8_t *buffer, uint16_t length); void W5500Process(void); extern void w5500_test(void); #endif
#include#include "stm32f10x.h"
#include "stm32f10x_spi.h"
#include "target.h"
#include "delay.h"
#include "w5500.h"
#include "w5500_queue.h"
#include "debug.h"
static uint8_t gateway_addr[4];
static uint8_t sub_mask[4];
static uint8_t mac_addr[6];
static uint8_t ip_addr[4];
static uint8_t s0_port[2]; //端口0的端口号(5000)
static uint8_t s0_dip[4]; //端口0目的IP地址
static uint8_t s0_dport[2]; //端口0目的端口号(6000)
static uint8_t udp_daddr[4]; //UDP(广播)模式,目的主机IP地址
static uint8_t udp_dport[2]; //UDP(广播)模式,目的主机端口号
/***************----- 端口的运行模式 -----***************/
static uint8_t s0_mode = 3; //端口0的运行模式,0:TCP服务器模式,1:TCP客户端模式,2:UDP(广播)模式
#define TCP_SERVER 0x00 //TCP服务器模式
#define TCP_CLIENT 0x01 //TCP客户端模式
#define UDP_MODE 0x02 //UDP(广播)模式
/***************----- 端口的运行状态 -----***************/
static uint8_t s0_state = 0; //端口0状态记录,1:端口完成初始化,2端口完成连接(可以正常传输数据)
#define S_INIT 0x01 //端口完成初始化
#define S_CONN 0x02 //端口完成连接,可以正常传输数据
/***************----- 端口收发数据的状态 -----***************/
static uint8_t s0_data; //端口0接收和发送数据的状态,1:端口接收到数据,2:端口发送数据完成
#define S_RECEIVE 0x01 //端口接收到一个数据包
#define S_TRANSMITOK 0x02 //端口发送一个数据包完成
/***************----- 端口数据缓冲区 -----***************/
uint8_t socket_rx_buffer[2048]; //端口接收数据缓冲区
uint8_t socket_tx_buffer[2048]; //端口发送数据缓冲区
static void w5500_gpio_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
W5500_RST_CONFIG();
W5500_RST_LOW();
W5500_INT_CONFIG();
W5500_CS_CONFIG();
W5500_SPI_CONFIG(); // clk miso mosi
}
static void w5500_spi_init(void)
{
SPI_InitTypeDef SPI_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
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(W5500_SPI, &SPI_InitStructure);
SPI_Cmd(W5500_SPI, ENABLE);
}
static void w5500_send_byte(uint8_t data)
{
SPI_I2S_SendData(W5500_SPI, data);//写1个字节数据
while(SPI_I2S_GetFlagStatus(W5500_SPI, SPI_I2S_FLAG_TXE) == RESET);//等待数据寄存器空
}
static void w5500_send_short(uint16_t data)
{
w5500_send_byte(data / 256);
w5500_send_byte(data);
}
static void w5500_write_byte(uint16_t reg, uint8_t data)
{
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM1 | RWB_WRITE | COMMON_R); // 写控制字节,1个字节数据长度,写数据,选择通用寄存器
w5500_send_byte(data);
W5500_CS_HIGH();
}
static void w5500_write_short(uint16_t reg, uint16_t data)
{
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM2 | RWB_WRITE | COMMON_R); // 写控制字节,2个字节数据长度,写数据,选择通用寄存器
w5500_send_short(data);
W5500_CS_HIGH();
}
static void w5500_write(uint16_t reg, uint8_t *buffer, uint16_t length)
{
uint16_t i;
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(VDM | RWB_WRITE | COMMON_R);
for(i = 0; i < length; ++i)
{
w5500_send_byte(*buffer++);
}
W5500_CS_HIGH();
}
static void w5500_sock_write_byte(SOCKET s, uint16_t reg, uint8_t data)
{
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM1 | RWB_WRITE | (s * 0x20 + 0x08)); // 写控制字节,1个字节数据长度,写数据,选择端口s的寄存器
w5500_send_byte(data);
W5500_CS_HIGH();
}
static void w5500_sock_write_short(SOCKET s, uint16_t reg, uint16_t data)
{
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM2 | RWB_WRITE | (s * 0x20 + 0x08)); // 写控制字节,2个字节数据长度,写数据,选择端口s的寄存器
w5500_send_short(data);
W5500_CS_HIGH();
}
static void w5500_sock_write_4bytes(SOCKET s, uint16_t reg, uint8_t *buffer)
{
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM4 | RWB_WRITE | (s * 0x20 + 0x08)); // 写控制字节,4个字节数据长度,写数据,选择端口s的寄存器
w5500_send_byte(*buffer++);
w5500_send_byte(*buffer++);
w5500_send_byte(*buffer++);
w5500_send_byte(*buffer++);
W5500_CS_HIGH();
}
static uint8_t w5500_read_byte(uint16_t reg)
{
uint8_t value;
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM1 | RWB_READ | COMMON_R); // 写控制字节,1个字节数据长度,读数据,选择通用寄存器
value = SPI_I2S_ReceiveData(W5500_SPI);
w5500_send_byte(0x00);
value = SPI_I2S_ReceiveData(W5500_SPI);
W5500_CS_HIGH();
return value;
}
static uint8_t w5500_sock_read_byte(SOCKET s, uint16_t reg)
{
uint8_t value;
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM1 | RWB_READ | (s * 0x20 + 0x08)); // 写控制字节,1个字节数据长度,读数据,选择端口s的寄存器
value = SPI_I2S_ReceiveData(W5500_SPI);
w5500_send_byte(0x00);
value = SPI_I2S_ReceiveData(W5500_SPI);
W5500_CS_HIGH();
return value;
}
static uint16_t w5500_sock_read_2bytes(SOCKET s, uint16_t reg)
{
uint16_t value;
W5500_CS_LOW();
w5500_send_short(reg);
w5500_send_byte(FDM2 | RWB_READ | (s * 0x20 + 0x08)); // 写控制字节,2个字节数据长度,读数据,选择端口s的寄存器
value = SPI_I2S_ReceiveData(W5500_SPI);
w5500_send_byte(0x00);
value = SPI_I2S_ReceiveData(W5500_SPI);
w5500_send_byte(0x00);
value *= 256;
value += SPI_I2S_ReceiveData(W5500_SPI);
W5500_CS_HIGH();
return value;
}
static uint16_t w5500_socket_read(SOCKET s, uint8_t *buffer)
{
uint16_t rx_size, offset, offset1, i;
uint8_t j;
rx_size = w5500_sock_read_2bytes(s, Sn_RX_RSR);
if(rx_size == 0)
{
return 0; //没接收到数据则返回
}
if(rx_size > 1460)
{
rx_size = 1460;
}
offset = w5500_sock_read_2bytes(s, Sn_RX_RD);
offset1 = offset;
offset &= (S_RX_SIZE - 1); //计算实际的物理地址
W5500_CS_LOW();
w5500_send_short(offset);//写16位地址
w5500_send_byte(VDM | RWB_READ | (s * 0x20 + 0x18)); //写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
j = SPI_I2S_ReceiveData(SPI2);
if((offset + rx_size) < S_RX_SIZE) //如果最大地址未超过W5500接收缓冲区寄存器的最大地址
{
for(i = 0; i < rx_size; i++) //循环读取rx_size个字节数据
{
w5500_send_byte(0x00);//发送一个哑数据
j = SPI_I2S_ReceiveData(SPI2); //读取1个字节数据
*buffer = j; //将读取到的数据保存到数据保存缓冲区
buffer++;//数据保存缓冲区指针地址自增1
}
}
else//如果最大地址超过W5500接收缓冲区寄存器的最大地址
{
offset = S_RX_SIZE - offset;
for(i = 0; i < offset; i++) //循环读取出前offset个字节数据
{
w5500_send_byte(0x00);//发送一个哑数据
j = SPI_I2S_ReceiveData(SPI2); //读取1个字节数据
*buffer = j; //将读取到的数据保存到数据保存缓冲区
buffer++;//数据保存缓冲区指针地址自增1
}
W5500_CS_HIGH();
W5500_CS_LOW();
w5500_send_short(0x00);//写16位地址
w5500_send_byte(VDM | RWB_READ | (s * 0x20 + 0x18)); //写控制字节,N个字节数据长度,读数据,选择端口s的寄存器
j = SPI_I2S_ReceiveData(SPI2);
for(; i < rx_size; i++) //循环读取后rx_size-offset个字节数据
{
w5500_send_byte(0x00);//发送一个哑数据
j = SPI_I2S_ReceiveData(SPI2); //读取1个字节数据
*buffer = j; //将读取到的数据保存到数据保存缓冲区
buffer++;//数据保存缓冲区指针地址自增1
}
}
W5500_CS_HIGH();
offset1 += rx_size; //更新实际物理地址,即下次读取接收到的数据的起始地址
w5500_sock_write_short(s, Sn_RX_RD, offset1);
w5500_sock_write_byte(s, Sn_CR, RECV);//发送启动接收命令
return rx_size;//返回接收到数据的长度
}
static void w5500_socket_write(SOCKET s, uint8_t *buffer, uint16_t length)
{
uint16_t offset, offset1, i;
//如果是UDP模式,可以在此设置目的主机的IP和端口号
if((w5500_sock_read_byte(s, Sn_MR) & 0x0f) != SOCK_UDP) //如果Socket打开失败
{
w5500_sock_write_4bytes(s, Sn_DIPR, udp_daddr);//设置目的主机IP
w5500_sock_write_short(s, Sn_DPORTR, udp_dport[0] * 256 + udp_dport[1]); //设置目的主机端口号
}
offset = w5500_sock_read_2bytes(s, Sn_TX_WR);
offset1 = offset;
offset &= (S_TX_SIZE - 1); //计算实际的物理地址
W5500_CS_LOW();
w5500_send_short(offset);//写16位地址
w5500_send_byte(VDM | RWB_WRITE | (s * 0x20 + 0x10)); //写控制字节,N个字节数据长度,写数据,选择端口s的寄存器
if((offset + length) < S_TX_SIZE) //如果最大地址未超过W5500发送缓冲区寄存器的最大地址
{
for(i = 0; i < length; ++i) //循环写入size个字节数据
{
w5500_send_byte(*buffer++);//写入一个字节的数据
}
}
else//如果最大地址超过W5500发送缓冲区寄存器的最大地址
{
offset = S_TX_SIZE - offset;
for(i = 0; i < offset; ++i) //循环写入前offset个字节数据
{
w5500_send_byte(*buffer++);//写入一个字节的数据
}
W5500_CS_HIGH();
W5500_CS_LOW();
w5500_send_short(0x00);//写16位地址
w5500_send_byte(VDM | RWB_WRITE | (s * 0x20 + 0x10)); //写控制字节,N个字节数据长度,写数据,选择端口s的寄存器
for(; i < length; i++) //循环写入size-offset个字节数据
{
w5500_send_byte(*buffer++);//写入一个字节的数据
}
}
W5500_CS_HIGH();
offset1 += length; //更新实际物理地址,即下次写待发送数据到发送数据缓冲区的起始地址
w5500_sock_write_short(s, Sn_TX_WR, offset1);
w5500_sock_write_byte(s, Sn_CR, SEND);//发送启动发送命令
}
static void w5500_hardware_reset(void)
{
W5500_RST_LOW();
delay_ms(5);
W5500_RST_HIGH();
delay_ms(20);
while((w5500_read_byte(PHYCFGR) & LINK) == 0);//等待以太网连接完成
}
static void w5500_reg_init(void)
{
uint8_t i = 0;
w5500_write_byte(MR, RST);//软件复位W5500,置1有效,复位后自动清0
delay_ms(10);
//设置网关(Gateway)的IP地址,Gateway_IP为4字节unsigned char数组,自己定义
//使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet
w5500_write(GAR, gateway_addr, 4);
//设置子网掩码(MASK)值,SUB_MASK为4字节unsigned char数组,自己定义
//子网掩码用于子网运算
w5500_write(SUBR, sub_mask, 4);
//设置物理地址,PHY_ADDR为6字节unsigned char数组,自己定义,用于唯一标识网络设备的物理地址值
//该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号
//如果自己定义物理地址,注意第一个字节必须为偶数
w5500_write(SHAR, mac_addr, 6);
//设置本机的IP地址,IP_ADDR为4字节unsigned char数组,自己定义
//注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关
w5500_write(SIPR, ip_addr, 4);
//设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册
for(i = 0; i < 8; i++)
{
w5500_sock_write_byte(i, Sn_RXBUF_SIZE, 0x02); //Socket Rx memory size=2k
w5500_sock_write_byte(i, Sn_TXBUF_SIZE, 0x02); //Socket Tx mempry size=2k
}
//设置重试时间,默认为2000(200ms)
//每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒
w5500_write_short(RTR_w5500, 0x07d0);
//设置重试次数,默认为8次
//如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)
w5500_write_byte(RCR_w5500, 8);
//启动中断,参考W5500数据手册确定自己需要的中断类型
//IMR_CONFLICT是IP地址冲突异常中断,IMR_UNREACH是UDP通信时,地址无法到达的异常中断
//其它是Socket事件中断,根据需要添加
w5500_write_byte(IMR, IM_IR7 | IM_IR6);
w5500_write_byte(SIMR, S0_IMR);
w5500_sock_write_byte(0, Sn_IMR, IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);
}
static uint8_t w5500_gateway_check(void)
{
uint8_t ip_adde[4];
ip_adde[0] = ip_addr[0] + 1;
ip_adde[1] = ip_addr[1] + 1;
ip_adde[2] = ip_addr[2] + 1;
ip_adde[3] = ip_addr[3] + 1;
//检查网关及获取网关的物理地址
w5500_sock_write_4bytes(0, Sn_DIPR, ip_adde); //向目的地址寄存器写入与本机IP不同的IP值
w5500_sock_write_byte(0, Sn_MR, MR_TCP); //设置socket为TCP模式
w5500_sock_write_byte(0, Sn_CR, OPEN); //打开Socket
delay_ms(5);//延时5ms
if(w5500_sock_read_byte(0, Sn_SR) != SOCK_INIT) //如果socket打开失败
{
w5500_sock_write_byte(0, Sn_CR, CLOSE); //打开不成功,关闭Socket
return SOCKET_FAILURE;//返回FALSE(0x00)
}
w5500_sock_write_byte(0, Sn_CR, CONNECT); //设置Socket为Connect模式
do
{
uint8_t j = 0;
j = w5500_sock_read_byte(0, Sn_IR); //读取Socket0中断标志寄存器
if(j != 0)
{
w5500_sock_write_byte(0, Sn_IR, j);
}
delay_ms(5);//延时5ms
if((j & IR_TIMEOUT) == IR_TIMEOUT)
{
return SOCKET_FAILURE;
}
else if(w5500_sock_read_byte(0, Sn_DHAR) != 0xff)
{
w5500_sock_write_byte(0, Sn_CR, CLOSE); //关闭Socket
return SOCKET_OK;
}
}
while(1);
}
static void w5500_socket_init(SOCKET s)
{
//设置分片长度,参考W5500数据手册,该值可以不修改
w5500_sock_write_short(0, Sn_MSSR, 1460);//最大分片字节数=1460(0x5b4)
//设置指定端口
switch(s)
{
case 0:
{
if(UDP_MODE == s0_mode)
{
//设置端口0的端口号
w5500_sock_write_short(0, Sn_PORT, s0_port[0] * 256 + s0_port[1]);
}
else if(TCP_CLIENT == s0_mode)
{
//设置端口0的端口号
w5500_sock_write_short(0, Sn_PORT, s0_port[0] * 256 + s0_port[1]);
//设置端口0目的(远程)端口号
w5500_sock_write_short(0, Sn_DPORTR, s0_dport[0] * 256 + s0_dport[1]);
//设置端口0目的(远程)IP地址
w5500_sock_write_4bytes(0, Sn_DIPR, s0_dip);
}
else if(TCP_SERVER == s0_mode)
{
//设置端口0的端口号
w5500_sock_write_short(0, Sn_PORT, s0_port[0] * 256 + s0_port[1]);
}
}
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
break;
}
}
static uint8_t w5500_socket_connect(SOCKET s)
{
w5500_sock_write_byte(s, Sn_MR, MR_TCP);
w5500_sock_write_byte(s, Sn_CR, OPEN);
delay_ms(5);
if(w5500_sock_read_byte(s, Sn_SR) != SOCK_INIT)
{
w5500_sock_write_byte(s, Sn_CR, CLOSE);
return SOCKET_FAILURE;
}
w5500_sock_write_byte(s, Sn_CR, CONNECT);
return SOCKET_OK;
}
static uint8_t w5500_socket_listen(SOCKET s)
{
w5500_sock_write_byte(s, Sn_MR, MR_TCP);
w5500_sock_write_byte(s, Sn_CR, OPEN);
delay_ms(5);
if(w5500_sock_read_byte(s, Sn_SR) != SOCK_INIT)
{
w5500_sock_write_byte(s, Sn_CR, CLOSE);
return SOCKET_FAILURE;
}
w5500_sock_write_byte(s, Sn_CR, LISTEN);
delay_ms(5);
if(w5500_sock_read_byte(s, Sn_SR) != SOCK_LISTEN)
{
w5500_sock_write_byte(s, Sn_CR, CLOSE);
return SOCKET_FAILURE;
}
return SOCKET_OK;
}
static uint8_t w5500_socket_udp(SOCKET s)
{
w5500_sock_write_byte(s, Sn_MR, MR_UDP);
w5500_sock_write_byte(s, Sn_CR, OPEN);
delay_ms(5);
if(w5500_sock_read_byte(s, Sn_SR) != SOCK_UDP)
{
w5500_sock_write_byte(s, Sn_CR, CLOSE);
return SOCKET_FAILURE;
}
else
{
return SOCKET_OK;
}
}
static void w5500_load_para(void)
{
gateway_addr[0] = 192;
gateway_addr[1] = 168;
gateway_addr[2] = 1;
gateway_addr[3] = 1;
sub_mask[0] = 255;
sub_mask[1] = 255;
sub_mask[2] = 255;
sub_mask[3] = 0;
mac_addr[0] = 0x0c;
mac_addr[1] = 0x29;
mac_addr[2] = 0xab;
mac_addr[3] = 0x7c;
mac_addr[4] = 0x00;
mac_addr[5] = 0x02;
ip_addr[0] = 192;
ip_addr[1] = 168;
ip_addr[2] = 1;
ip_addr[3] = 199;
s0_port[0] = 0x18;
s0_port[1] = 0x56;
udp_daddr[0] = 192;
udp_daddr[1] = 168;
udp_daddr[2] = 1;
udp_daddr[3] = 190;
#if 0
s0_dip[0] = 192;
s0_dip[1] = 168;
s0_dip[2] = 1;
s0_dip[3] = 99;
s0_dport[0] = 0x18;
s0_dport[1] = 0x56;
#endif
udp_dport[0] = 0x17;
udp_dport[1] = 0x70;
s0_mode = UDP_MODE;
}
void W5500Init(void)
{
w5500_gpio_init();
w5500_spi_init();
w5500_load_para(); // load net para [ip, port, mask...]
w5500_hardware_reset();
w5500_reg_init();
w5500_gateway_check();
w5500_socket_init(0);
}
void W5500SocketScan(void)
{
if(s0_state == 0)
{
if(s0_mode == TCP_SERVER)
{
if(w5500_socket_listen(0) == SOCKET_OK)
{
s0_state = S_INIT;
}
else
{
s0_state = 0;
}
}
else if(s0_mode == TCP_CLIENT)
{
if(w5500_socket_connect(0) == SOCKET_OK)
{
s0_state = S_INIT;
}
else
{
s0_state = 0;
}
}
else
{
if(w5500_socket_udp(0) == SOCKET_OK)
{
debug("1234rn");
s0_state = S_INIT | S_CONN;
}
else
{
s0_state = 0;
}
}
}
}
uint16_t W5500SocketRecv(uint8_t *buffer)
{
uint16_t length;
if((s0_data & S_RECEIVE) == S_RECEIVE)
{
s0_data &= ~S_RECEIVE;
length = w5500_socket_read(0, buffer);
}
return length;
}
void W5500SocketSend(uint8_t *buffer, uint16_t length)
{
if(s0_state == (S_INIT | S_CONN))
{
s0_data &= ~S_TRANSMITOK;
w5500_socket_write(0, buffer, length);
}
}
void W5500InterruptProcess(void)
{
uint8_t i, j;
IntDispose:
i = w5500_read_byte(IR);//读取中断标志寄存器
w5500_write_byte(IR, (i & 0xf0));//回写清除中断标志
if((i & CONFLICT) == CONFLICT)//IP地址冲突异常处理
{
//自己添加代码
}
if((i & UNREACH) == UNREACH)//UDP模式下地址无法到达异常处理
{
debug("-------n");
//自己添加代码
}
i = w5500_read_byte(SIR); //读取端口中断标志寄存器
if((i & S0_INT) == S0_INT)//Socket0事件处理
{
j = w5500_sock_read_byte(0, Sn_IR); //读取Socket0中断标志寄存器
w5500_sock_write_byte(0, Sn_IR, j);
if(j & IR_CON) //在TCP模式下,Socket0成功连接
{
s0_state |= S_CONN; //网络连接状态0x02,端口完成连接,可以正常传输数据
}
if(j & IR_DISCON) //在TCP模式下Socket断开连接处理
{
w5500_sock_write_byte(0, Sn_CR, CLOSE); //关闭端口,等待重新打开连接
w5500_socket_init(0); //指定Socket(0~7)初始化,初始化端口0
s0_state = 0; //网络连接状态0x00,端口连接失败
}
if(j & IR_SEND_OK) //Socket0数据发送完成,可以再次启动S_tx_process()函数发送数据
{
s0_data |= S_TRANSMITOK; //端口发送一个数据包完成
}
if(j & IR_RECV) //Socket接收到数据,可以启动S_rx_process()函数
{
s0_data |= S_RECEIVE; //端口接收到一个数据包
}
if(j & IR_TIMEOUT) //Socket连接或数据传输超时处理
{
w5500_sock_write_byte(0, Sn_CR, CLOSE); // 关闭端口,等待重新打开连接
s0_state = 0; //网络连接状态0x00,端口连接失败
}
}
if(w5500_read_byte(SIR) != 0)
{
goto IntDispose;
}
}
// test use
static void socket_data_process(SOCKET s)
{
w5500_frame_t frame;
frame.length = w5500_socket_read(s, frame.data);
// debug("socket_data_process...rn");
W5500QueueWrite(&w5500_queue_recv, &frame);
if(UDP_MODE == s0_mode)
{
udp_daddr[0] = frame.data[0];
udp_daddr[1] = frame.data[1];
udp_daddr[2] = frame.data[2];
udp_daddr[3] = frame.data[3];
udp_dport[0] = frame.data[4];
udp_dport[1] = frame.data[5];
}
}
void W5500Process(void)
{
W5500SocketScan();
debug("22222rn");
W5500InterruptProcess();
debug("3333rn");
if((s0_data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到数据
{
s0_data &= ~S_RECEIVE;
socket_data_process(0);//W5500接收并发送接收到的数据
}
debug("1111rn");
}
void w5500_test(void)
{
static uint16_t W5500_Send_Delay_Counter = 0;
W5500_Send_Delay_Counter++;
W5500SocketScan();
W5500InterruptProcess();
if((s0_data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到数据
{
s0_data &= ~S_RECEIVE;
socket_data_process(0);//W5500接收并发送接收到的数据
}
else if(W5500_Send_Delay_Counter >= 500)//定时发送字符串
{
if(s0_state == (S_INIT | S_CONN))
{
s0_data &= ~S_TRANSMITOK;
memcpy(socket_tx_buffer, "rn123456rn", 10);
w5500_socket_write(0, socket_tx_buffer, 10);//指定Socket(0~7)发送数据处理,端口0发送23字节数据
W5500_Send_Delay_Counter = 0;
}
}
}




