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; } } }