w5500跨网段_基于STM32F1的局域网通信模块W5500驱动

说明

需要调整的内容为W5500.h中关于IP地址、端口号、子网掩码、网关等参数

W5500

#ifndef_W5500_H_

#define_W5500_H_

/****************** Parameter **********************/

//网关地址

#define GATEWAY_IP_0 125

#define GATEWAY_IP_1 217

#define GATEWAY_IP_2 54

#define GATEWAY_IP_3 254

#define SUB_MASK_0 255

#define SUB_MASK_1 255

#define SUB_MASK_2 255

#define SUB_MASK_3 0

#define PHY_ADDR_0 0x80

#define PHY_ADDR_1 0x9E

#define PHY_ADDR_2 0x01

#define PHY_ADDR_3 0x56

#define PHY_ADDR_4 0x37

#define PHY_ADDR_5 0xC6

//本机IP地址

#define IP_ADDR_0 125

#define IP_ADDR_1 217

#define IP_ADDR_2 54

#define IP_ADDR_3 55

//本机端口号

#define S0_PORT_0 0x13

#define S0_PORT_1 0x88

//UDP(广播)模式,目的主机IP地址

#define UDP_DIR_0 125

#define UDP_DIR_1 217

#define UDP_DIR_2 54

#define UDP_DIR_3 242

//UDP(广播)模式,目的主机端口号

#define UDP_DPORT_0 0x17

#define UDP_DPORT_1 0x75

//模式配置

#define S0_MODE UDP_MODE

/***************** Common Register *****************/

#define MR0x0000

#define RST0x80

#define WOL0x20

#define PB0x10

#define PPP0x08

#define FARP0x02

#define GAR0x0001

#define SUBR0x0005

#define SHAR0x0009

#define SIPR0x000f

#define INTLEVEL0x0013

#define IR0x0015

#define CONFLICT0x80

#define UNREACH0x40

#define PPPOE0x20

#define MP0x10

#define IMR0x0016

#define IM_IR70x80

#define IM_IR60x40

#define IM_IR50x20

#define IM_IR40x10

#define SIR0x0017

#define S7_INT0x80

#define S6_INT0x40

#define S5_INT0x20

#define S4_INT0x10

#define S3_INT0x08

#define S2_INT0x04

#define S1_INT0x02

#define S0_INT0x01

#define SIMR0x0018

#define S7_IMR0x80

#define S6_IMR0x40

#define S5_IMR0x20

#define S4_IMR0x10

#define S3_IMR0x08

#define S2_IMR0x04

#define S1_IMR0x02

#define S0_IMR0x01

#define RTR0x0019

#define RCR0x001b

#define PTIMER0x001c

#define PMAGIC0x001d

#define PHA0x001e

#define PSID0x0024

#define PMRU0x0026

#define UIPR0x0028

#define UPORT0x002c

#define PHYCFGR0x002e

#define RST_PHY0x80

#define OPMODE0x40

#define DPX0x04

#define SPD0x02

#define LINK0x01

#define VERR0x0039

/********************* Socket Register *******************/

#define Sn_MR0x0000

#define MULTI_MFEN0x80

#define BCASTB0x40

#defineND_MC_MMB0x20

#define UCASTB_MIP6B0x10

#define MR_CLOSE0x00

#define MR_TCP0x01

#define MR_UDP0x02

#define MR_MACRAW0x04

#define Sn_CR0x0001

#define OPEN0x01

#define LISTEN0x02

#define CONNECT0x04

#define DISCON0x08

#define CLOSE0x10

#define SEND0x20

#define SEND_MAC0x21

#define SEND_KEEP0x22

#define RECV0x40

#define Sn_IR0x0002

#define IR_SEND_OK0x10

#define IR_TIMEOUT0x08

#define IR_RECV0x04

#define IR_DISCON0x02

#define IR_CON0x01

#define Sn_SR0x0003

#define SOCK_CLOSED0x00

#define SOCK_INIT0x13

#define SOCK_LISTEN0x14

#define SOCK_ESTABLISHED0x17

#define SOCK_CLOSE_WAIT0x1c

#define SOCK_UDP0x22

#define SOCK_MACRAW0x02

#define SOCK_SYNSEND0x15

#define SOCK_SYNRECV0x16

#define SOCK_FIN_WAI0x18

#define SOCK_CLOSING0x1a

#define SOCK_TIME_WAIT0x1b

#define SOCK_LAST_ACK0x1d

#define Sn_PORT0x0004

#define Sn_DHAR 0x0006

#define Sn_DIPR0x000c

#define Sn_DPORTR0x0010

#define Sn_MSSR0x0012

#define Sn_TOS0x0015

#define Sn_TTL0x0016

#define Sn_RXBUF_SIZE0x001e

#define Sn_TXBUF_SIZE0x001f

#define Sn_TX_FSR0x0020

#define Sn_TX_RD0x0022

#define Sn_TX_WR0x0024

#define Sn_RX_RSR0x0026

#define Sn_RX_RD0x0028

#define Sn_RX_WR0x002a

#define Sn_IMR0x002c

#define IMR_SENDOK0x10

#define IMR_TIMEOUT0x08

#define IMR_RECV0x04

#define IMR_DISCON0x02

#define IMR_CON0x01

#define Sn_FRAG0x002d

#define Sn_KPALVTR0x002f

/*******************************************************************/

/************************ SPI Control Byte *************************/

/*******************************************************************/

/* Operation mode bits */

#define VDM0x00

#define FDM10x01

#defineFDM20x02

#define FDM40x03

/* Read_Write control bit */

#define RWB_READ0x00

#define RWB_WRITE0x04

/* Block select bits */

#define COMMON_R0x00

/* Socket 0 */

#define S0_REG0x08

#define S0_TX_BUF0x10

#define S0_RX_BUF0x18

/* Socket 1 */

#define S1_REG0x28

#define S1_TX_BUF0x30

#define S1_RX_BUF0x38

/* Socket 2 */

#define S2_REG0x48

#define S2_TX_BUF0x50

#define S2_RX_BUF0x58

/* Socket 3 */

#define S3_REG0x68

#define S3_TX_BUF0x70

#define S3_RX_BUF0x78

/* Socket 4 */

#define S4_REG0x88

#define S4_TX_BUF0x90

#define S4_RX_BUF0x98

/* Socket 5 */

#define S5_REG0xa8

#define S5_TX_BUF0xb0

#define S5_RX_BUF0xb8

/* Socket 6 */

#define S6_REG0xc8

#define S6_TX_BUF0xd0

#define S6_RX_BUF0xd8

/* Socket 7 */

#define S7_REG0xe8

#define S7_TX_BUF0xf0

#define S7_RX_BUF0xf8

#define TRUE0xff

#define FALSE0x00

#define S_RX_SIZE2048/*定义Socket接收缓冲区的大小,可以根据W5500_RMSR的设置修改 */

#define S_TX_SIZE2048 /*定义Socket发送缓冲区的大小,可以根据W5500_TMSR的设置修改 */

/***************----- W5500 GPIO定义 -----***************/

#define W5500_SCSGPIO_Pin_4//定义W5500的CS引脚

#define W5500_SCS_PORTGPIOA

#define W5500_RSTGPIO_Pin_0//定义W5500的RST引脚

#define W5500_RST_PORTGPIOB

#define W5500_INTGPIO_Pin_1//定义W5500的INT引脚

#define W5500_INT_PORTGPIOB

/***************----- 网络参数变量定义 -----***************/

extern unsigned char Gateway_IP[4];//网关IP地址

extern unsigned char Sub_Mask[4];//子网掩码

extern unsigned char Phy_Addr[6];//物理地址(MAC)

extern unsigned char IP_Addr[4];//本机IP地址

extern unsigned char S0_Port[2];//端口0的端口号(5000)

extern unsigned char S0_DIP[4];//端口0目的IP地址

extern unsigned char S0_DPort[2];//端口0目的端口号(6000)

extern unsigned char UDP_DIPR[4];//UDP(广播)模式,目的主机IP地址

extern unsigned char UDP_DPORT[2];//UDP(广播)模式,目的主机端口号

/***************----- 端口的运行模式 -----***************/

extern unsigned char S0_Mode;//端口0的运行模式,0:TCP服务器模式,1:TCP客户端模式,2:UDP(广播)模式

#define TCP_SERVER0x00//TCP服务器模式

#define TCP_CLIENT0x01//TCP客户端模式

#define UDP_MODE0x02//UDP(广播)模式

/***************----- 端口的运行状态 -----***************/

extern unsigned char S0_State;//端口0状态记录,1:端口完成初始化,2端口完成连接(可以正常传输数据)

#define S_INIT0x01//端口完成初始化

#define S_CONN0x02//端口完成连接,可以正常传输数据

/***************----- 端口收发数据的状态 -----***************/

extern unsigned char S0_Data;//端口0接收和发送数据的状态,1:端口接收到数据,2:端口发送数据完成

#define S_RECEIVE0x01//端口接收到一个数据包

#define S_TRANSMITOK0x02//端口发送一个数据包完成

/***************----- 端口数据缓冲区 -----***************/

extern unsigned char Rx_Buffer[2048];//端口接收数据缓冲区

extern unsigned char Tx_Buffer[2048];//端口发送数据缓冲区

extern unsigned char W5500_Interrupt;//W5500中断标志(0:无中断,1:有中断)

typedef unsigned char SOCKET;//自定义端口号数据类型

extern void Delay(unsigned int d);//延时函数(ms)

extern void W5500_GPIO_Configuration(void);//W5500 GPIO初始化配置

extern void W5500_NVIC_Configuration(void);//W5500 接收引脚中断优先级设置

extern void SPI_Configuration(void);//W5500 SPI初始化配置(STM32 SPI1)

extern void W5500_Hardware_Reset(void);//硬件复位W5500

extern void W5500_Init(void);//初始化W5500寄存器函数

extern unsigned char Detect_Gateway(void);//检查网关服务器

extern void Socket_Init(SOCKET s);//指定Socket(0~7)初始化

extern unsigned char Socket_Connect(SOCKET s);//设置指定Socket(0~7)为客户端与远程服务器连接

extern unsigned char Socket_Listen(SOCKET s);//设置指定Socket(0~7)作为服务器等待远程主机的连接

extern unsigned char Socket_UDP(SOCKET s);//设置指定Socket(0~7)为UDP模式

extern unsigned short Read_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr);//指定Socket(0~7)接收数据处理

extern void Write_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr, unsigned short size); //指定Socket(0~7)发送数据处理

extern void W5500_Interrupt_Process(void);//W5500中断处理程序框架

void NVIC_Configuration(void);

void RCC_Configuration(void);

void Timer2_Init_Config(void);

void SendData(unsigned char* data,int length);

void My_W5500_Init(void);

void W5500_Socket_Set(void);

void Process_Socket_Data(SOCKET s);

#endif

W5500.c

/**********************************************************************************

* 文件名 :W5500.c

* 描述 :W5500 驱动函数库

* 库版本 :ST_v3.5

**********************************************************************************/

#include "stm32f10x.h"

#include "stm32f10x_spi.h"

#include "W5500.h"

#include

/***************----- 网络参数变量定义 -----***************/

unsigned char Gateway_IP[4];//网关IP地址

unsigned char Sub_Mask[4];//子网掩码

unsigned char Phy_Addr[6];//物理地址(MAC)

unsigned char IP_Addr[4];//本机IP地址

unsigned char S0_Port[2];//端口0的端口号(5000)

unsigned char S0_DIP[4];//端口0目的IP地址

unsigned char S0_DPort[2];//端口0目的端口号(6000)

unsigned char UDP_DIPR[4];//UDP(广播)模式,目的主机IP地址

unsigned char UDP_DPORT[2];//UDP(广播)模式,目的主机端口号

/***************----- 端口的运行模式 -----***************/

unsigned char S0_Mode =3;//端口0的运行模式,0:TCP服务器模式,1:TCP客户端模式,2:UDP(广播)模式

#define TCP_SERVER0x00//TCP服务器模式

#define TCP_CLIENT0x01//TCP客户端模式

#define UDP_MODE0x02//UDP(广播)模式

/***************----- 端口的运行状态 -----***************/

unsigned char S0_State =0;//端口0状态记录,1:端口完成初始化,2端口完成连接(可以正常传输数据)

#define S_INIT0x01//端口完成初始化

#define S_CONN0x02//端口完成连接,可以正常传输数据

/***************----- 端口收发数据的状态 -----***************/

unsigned char S0_Data;//端口0接收和发送数据的状态,1:端口接收到数据,2:端口发送数据完成

#define S_RECEIVE 0x01//端口接收到一个数据包

#define S_TRANSMITOK 0x02//端口发送一个数据包完成

/***************----- 端口数据缓冲区 -----***************/

unsigned char Rx_Buffer[2048];//端口接收数据缓冲区

unsigned char Tx_Buffer[2048];//端口发送数据缓冲区

unsigned char W5500_Interrupt;//W5500中断标志(0:无中断,1:有中断)

unsigned int Timer2_Counter=0; //Timer2定时器计数变量(ms)

unsigned int W5500_Send_Delay_Counter=0; //W5500发送延时计数变量(ms)

/*******************************************************************************

* 函数名 : W5500_GPIO_Configuration

* 描述 : W5500 GPIO初始化配置

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void W5500_GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/* W5500_RST引脚初始化配置(PC5) */

GPIO_InitStructure.GPIO_Pin = W5500_RST;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(W5500_RST_PORT, &GPIO_InitStructure);

GPIO_ResetBits(W5500_RST_PORT, W5500_RST);

}

/*******************************************************************************

* 函数名 : SPI_Configuration

* 描述 : W5500 SPI初始化配置(STM32 SPI1)

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void SPI_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

SPI_InitTypeDef SPI_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);

/* 初始化SCK、MISO、MOSI引脚 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);

/* 初始化CS引脚 */

GPIO_InitStructure.GPIO_Pin = W5500_SCS;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

GPIO_Init(W5500_SCS_PORT, &GPIO_InitStructure);

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);

/* 初始化配置STM32 SPI1 */

SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//SPI设置为双线双向全双工

SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//设置为主SPI

SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//SPI发送接收8位帧结构

SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;//时钟悬空低

SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;//数据捕获于第1个时钟沿

SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//NSS由外部管脚管理

SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;//波特率预分频值为2

SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//数据传输从MSB位开始

SPI_InitStructure.SPI_CRCPolynomial=7;//CRC多项式为7

SPI_Init(SPI1,&SPI_InitStructure);//根据SPI_InitStruct中指定的参数初始化外设SPI1寄存器

SPI_Cmd(SPI1,ENABLE);//STM32使能SPI1

}

/*******************************************************************************

* 函数名 : SPI1_Send_Byte

* 描述 : SPI1发送1个字节数据

* 输入 : dat:待发送的数据

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void SPI1_Send_Byte(unsigned char dat)

{

SPI_I2S_SendData(SPI1,dat);//写1个字节数据

while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//等待数据寄存器空

}

/*******************************************************************************

* 函数名 : SPI1_Send_Short

* 描述 : SPI1发送2个字节数据(16位)

* 输入 : dat:待发送的16位数据

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void SPI1_Send_Short(unsigned short dat)

{

SPI1_Send_Byte(dat/256);//写数据高位

SPI1_Send_Byte(dat);//写数据低位

}

/*******************************************************************************

* 函数名 : Write_W5500_1Byte

* 描述 : 通过SPI1向指定地址寄存器写1个字节数据

* 输入 : reg:16位寄存器地址,dat:待写入的数据

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_W5500_1Byte(unsigned short reg, unsigned char dat)

{

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM1|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,1个字节数据长度,写数据,选择通用寄存器

SPI1_Send_Byte(dat);//写1个字节数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

}

/*******************************************************************************

* 函数名 : Write_W5500_2Byte

* 描述 : 通过SPI1向指定地址寄存器写2个字节数据

* 输入 : reg:16位寄存器地址,dat:16位待写入的数据(2个字节)

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_W5500_2Byte(unsigned short reg, unsigned short dat)

{

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM2|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,2个字节数据长度,写数据,选择通用寄存器

SPI1_Send_Short(dat);//写16位数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

}

/*******************************************************************************

* 函数名 : Write_W5500_nByte

* 描述 : 通过SPI1向指定地址寄存器写n个字节数据

* 输入 : reg:16位寄存器地址,*dat_ptr:待写入数据缓冲区指针,size:待写入的数据长度

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_W5500_nByte(unsigned short reg, unsigned char *dat_ptr, unsigned short size)

{

unsigned short i;

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(VDM|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,N个字节数据长度,写数据,选择通用寄存器

for(i=0;i

{

SPI1_Send_Byte(*dat_ptr++);//写一个字节数据

}

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

}

/*******************************************************************************

* 函数名 : Write_W5500_SOCK_1Byte

* 描述 : 通过SPI1向指定端口寄存器写1个字节数据

* 输入 : s:端口号,reg:16位寄存器地址,dat:待写入的数据

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_W5500_SOCK_1Byte(SOCKET s, unsigned short reg, unsigned char dat)

{

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM1|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,1个字节数据长度,写数据,选择端口s的寄存器

SPI1_Send_Byte(dat);//写1个字节数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

}

/*******************************************************************************

* 函数名 : Write_W5500_SOCK_2Byte

* 描述 : 通过SPI1向指定端口寄存器写2个字节数据

* 输入 : s:端口号,reg:16位寄存器地址,dat:16位待写入的数据(2个字节)

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_W5500_SOCK_2Byte(SOCKET s, unsigned short reg, unsigned short dat)

{

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM2|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,2个字节数据长度,写数据,选择端口s的寄存器

SPI1_Send_Short(dat);//写16位数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

}

/*******************************************************************************

* 函数名 : Write_W5500_SOCK_4Byte

* 描述 : 通过SPI1向指定端口寄存器写4个字节数据

* 输入 : s:端口号,reg:16位寄存器地址,*dat_ptr:待写入的4个字节缓冲区指针

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_W5500_SOCK_4Byte(SOCKET s, unsigned short reg, unsigned char *dat_ptr)

{

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM4|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,4个字节数据长度,写数据,选择端口s的寄存器

SPI1_Send_Byte(*dat_ptr++);//写第1个字节数据

SPI1_Send_Byte(*dat_ptr++);//写第2个字节数据

SPI1_Send_Byte(*dat_ptr++);//写第3个字节数据

SPI1_Send_Byte(*dat_ptr++);//写第4个字节数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

}

/*******************************************************************************

* 函数名 : Read_W5500_1Byte

* 描述 : 读W5500指定地址寄存器的1个字节数据

* 输入 : reg:16位寄存器地址

* 输出 : 无

* 返回值 : 读取到寄存器的1个字节数据

* 说明 : 无

*******************************************************************************/

unsigned char Read_W5500_1Byte(unsigned short reg)

{

unsigned char i;

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM1|RWB_READ|COMMON_R);//通过SPI1写控制字节,1个字节数据长度,读数据,选择通用寄存器

i=SPI_I2S_ReceiveData(SPI1);

SPI1_Send_Byte(0x00);//发送一个哑数据

i=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平

return i;//返回读取到的寄存器数据

}

/*******************************************************************************

* 函数名 : Read_W5500_SOCK_1Byte

* 描述 : 读W5500指定端口寄存器的1个字节数据

* 输入 : s:端口号,reg:16位寄存器地址

* 输出 : 无

* 返回值 : 读取到寄存器的1个字节数据

* 说明 : 无

*******************************************************************************/

unsigned char Read_W5500_SOCK_1Byte(SOCKET s, unsigned short reg)

{

unsigned char i;

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM1|RWB_READ|(s*0x20+0x08));//通过SPI1写控制字节,1个字节数据长度,读数据,选择端口s的寄存器

i=SPI_I2S_ReceiveData(SPI1);

SPI1_Send_Byte(0x00);//发送一个哑数据

i=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平

return i;//返回读取到的寄存器数据

}

/*******************************************************************************

* 函数名 : Read_W5500_SOCK_2Byte

* 描述 : 读W5500指定端口寄存器的2个字节数据

* 输入 : s:端口号,reg:16位寄存器地址

* 输出 : 无

* 返回值 : 读取到寄存器的2个字节数据(16位)

* 说明 : 无

*******************************************************************************/

unsigned short Read_W5500_SOCK_2Byte(SOCKET s, unsigned short reg)

{

unsigned short i;

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址

SPI1_Send_Byte(FDM2|RWB_READ|(s*0x20+0x08));//通过SPI1写控制字节,2个字节数据长度,读数据,选择端口s的寄存器

i=SPI_I2S_ReceiveData(SPI1);

SPI1_Send_Byte(0x00);//发送一个哑数据

i=SPI_I2S_ReceiveData(SPI1);//读取高位数据

SPI1_Send_Byte(0x00);//发送一个哑数据

i*=256;

i+=SPI_I2S_ReceiveData(SPI1);//读取低位数据

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平

return i;//返回读取到的寄存器数据

}

/*******************************************************************************

* 函数名 : Read_SOCK_Data_Buffer

* 描述 : 从W5500接收数据缓冲区中读取数据

* 输入 : s:端口号,*dat_ptr:数据保存缓冲区指针

* 输出 : 无

* 返回值 : 读取到的数据长度,rx_size个字节

* 说明 : 无

*******************************************************************************/

unsigned short Read_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr)

{

unsigned short rx_size;

unsigned short offset, offset1;

unsigned short i;

unsigned char j;

rx_size=Read_W5500_SOCK_2Byte(s,Sn_RX_RSR);

if(rx_size==0) return 0;//没接收到数据则返回

if(rx_size>1460) rx_size=1460;

offset=Read_W5500_SOCK_2Byte(s,Sn_RX_RD);

offset1=offset;

offset&=(S_RX_SIZE-1);//计算实际的物理地址

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(offset);//写16位地址

SPI1_Send_Byte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器

j=SPI_I2S_ReceiveData(SPI1);

if((offset+rx_size)

{

for(i=0;i

{

SPI1_Send_Byte(0x00);//发送一个哑数据

j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据

*dat_ptr=j;//将读取到的数据保存到数据保存缓冲区

dat_ptr++;//数据保存缓冲区指针地址自增1

}

}

else//如果最大地址超过W5500接收缓冲区寄存器的最大地址

{

offset=S_RX_SIZE-offset;

for(i=0;i

{

SPI1_Send_Byte(0x00);//发送一个哑数据

j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据

*dat_ptr=j;//将读取到的数据保存到数据保存缓冲区

dat_ptr++;//数据保存缓冲区指针地址自增1

}

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(0x00);//写16位地址

SPI1_Send_Byte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器

j=SPI_I2S_ReceiveData(SPI1);

for(;i

{

SPI1_Send_Byte(0x00);//发送一个哑数据

j=SPI_I2S_ReceiveData(SPI1);//读取1个字节数据

*dat_ptr=j;//将读取到的数据保存到数据保存缓冲区

dat_ptr++;//数据保存缓冲区指针地址自增1

}

}

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

offset1+=rx_size;//更新实际物理地址,即下次读取接收到的数据的起始地址

Write_W5500_SOCK_2Byte(s, Sn_RX_RD, offset1);

Write_W5500_SOCK_1Byte(s, Sn_CR, RECV);//发送启动接收命令

return rx_size;//返回接收到数据的长度

}

/*******************************************************************************

* 函数名 : Write_SOCK_Data_Buffer

* 描述 : 将数据写入W5500的数据发送缓冲区

* 输入 : s:端口号,*dat_ptr:数据保存缓冲区指针,size:待写入数据的长度

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Write_SOCK_Data_Buffer(SOCKET s, unsigned char *dat_ptr, unsigned short size)

{

unsigned short offset,offset1;

unsigned short i;

//如果是UDP模式,可以在此设置目的主机的IP和端口号

if((Read_W5500_SOCK_1Byte(s,Sn_MR)&0x0f) != SOCK_UDP)//如果Socket打开失败

{

Write_W5500_SOCK_4Byte(s, Sn_DIPR, UDP_DIPR);//设置目的主机IP

Write_W5500_SOCK_2Byte(s, Sn_DPORTR, UDP_DPORT[0]*256+UDP_DPORT[1]);//设置目的主机端口号

}

offset=Read_W5500_SOCK_2Byte(s,Sn_TX_WR);

offset1=offset;

offset&=(S_TX_SIZE-1);//计算实际的物理地址

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(offset);//写16位地址

SPI1_Send_Byte(VDM|RWB_WRITE|(s*0x20+0x10));//写控制字节,N个字节数据长度,写数据,选择端口s的寄存器

if((offset+size)

{

for(i=0;i

{

SPI1_Send_Byte(*dat_ptr++);//写入一个字节的数据

}

}

else//如果最大地址超过W5500发送缓冲区寄存器的最大地址

{

offset=S_TX_SIZE-offset;

for(i=0;i

{

SPI1_Send_Byte(*dat_ptr++);//写入一个字节的数据

}

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

SPI1_Send_Short(0x00);//写16位地址

SPI1_Send_Byte(VDM|RWB_WRITE|(s*0x20+0x10));//写控制字节,N个字节数据长度,写数据,选择端口s的寄存器

for(;i

{

SPI1_Send_Byte(*dat_ptr++);//写入一个字节的数据

}

}

GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); //置W5500的SCS为高电平

offset1+=size;//更新实际物理地址,即下次写待发送数据到发送数据缓冲区的起始地址

Write_W5500_SOCK_2Byte(s, Sn_TX_WR, offset1);

Write_W5500_SOCK_1Byte(s, Sn_CR, SEND);//发送启动发送命令

}

/*******************************************************************************

* 函数名 : W5500_Hardware_Reset

* 描述 : 硬件复位W5500

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : W5500的复位引脚保持低电平至少500us以上,才能重围W5500

*******************************************************************************/

void W5500_Hardware_Reset(void)

{

GPIO_ResetBits(W5500_RST_PORT, W5500_RST);//复位引脚拉低

Delay(50);

GPIO_SetBits(W5500_RST_PORT, W5500_RST);//复位引脚拉高

Delay(200);

while((Read_W5500_1Byte(PHYCFGR)&LINK)==0);//等待以太网连接完成

}

/*******************************************************************************

* 函数名 : W5500_Init

* 描述 : 初始化W5500寄存器函数

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : 在使用W5500之前,先对W5500初始化

*******************************************************************************/

void W5500_Init(void)

{

u8 i=0;

Write_W5500_1Byte(MR, RST);//软件复位W5500,置1有效,复位后自动清0

Delay(10);//延时10ms,自己定义该函数

//设置网关(Gateway)的IP地址,Gateway_IP为4字节unsigned char数组,自己定义

//使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet

Write_W5500_nByte(GAR, Gateway_IP, 4);

//设置子网掩码(MASK)值,SUB_MASK为4字节unsigned char数组,自己定义

//子网掩码用于子网运算

Write_W5500_nByte(SUBR,Sub_Mask,4);

//设置物理地址,PHY_ADDR为6字节unsigned char数组,自己定义,用于唯一标识网络设备的物理地址值

//该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号

//如果自己定义物理地址,注意第一个字节必须为偶数

Write_W5500_nByte(SHAR,Phy_Addr,6);

//设置本机的IP地址,IP_ADDR为4字节unsigned char数组,自己定义

//注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关

Write_W5500_nByte(SIPR,IP_Addr,4);

//设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册

for(i=0;i<8;i++)

{

Write_W5500_SOCK_1Byte(i,Sn_RXBUF_SIZE, 0x02);//Socket Rx memory size=2k

Write_W5500_SOCK_1Byte(i,Sn_TXBUF_SIZE, 0x02);//Socket Tx mempry size=2k

}

//设置重试时间,默认为2000(200ms)

//每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒

Write_W5500_2Byte(RTR, 0x07d0);

//设置重试次数,默认为8次

//如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)

Write_W5500_1Byte(RCR,8);

}

/*******************************************************************************

* 函数名 : Detect_Gateway

* 描述 : 检查网关服务器

* 输入 : 无

* 输出 : 无

* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)

* 说明 : 无

*******************************************************************************/

unsigned char Detect_Gateway(void)

{

unsigned char 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;

//检查网关及获取网关的物理地址

Write_W5500_SOCK_4Byte(0,Sn_DIPR,ip_adde);//向目的地址寄存器写入与本机IP不同的IP值

Write_W5500_SOCK_1Byte(0,Sn_MR,MR_TCP);//设置socket为TCP模式

Write_W5500_SOCK_1Byte(0,Sn_CR,OPEN);//打开Socket

Delay(5);//延时5ms

if(Read_W5500_SOCK_1Byte(0,Sn_SR) != SOCK_INIT)//如果socket打开失败

{

Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//打开不成功,关闭Socket

return FALSE;//返回FALSE(0x00)

}

Write_W5500_SOCK_1Byte(0,Sn_CR,CONNECT);//设置Socket为Connect模式

do

{

u8 j=0;

j=Read_W5500_SOCK_1Byte(0,Sn_IR);//读取Socket0中断标志寄存器

if(j!=0)

Write_W5500_SOCK_1Byte(0,Sn_IR,j);

Delay(5);//延时5ms

if((j&IR_TIMEOUT) == IR_TIMEOUT)

{

return FALSE;

}

else if(Read_W5500_SOCK_1Byte(0,Sn_DHAR) != 0xff)

{

Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//关闭Socket

return TRUE;

}

}while(1);

}

/*******************************************************************************

* 函数名 : Socket_Init

* 描述 : 指定Socket(0~7)初始化

* 输入 : s:待初始化的端口

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void Socket_Init(SOCKET s)

{

//设置分片长度,参考W5500数据手册,该值可以不修改

Write_W5500_SOCK_2Byte(0, Sn_MSSR, 1460);//最大分片字节数=1460(0x5b4)

//设置指定端口

switch(s)

{

case 0:

//设置端口0的端口号

Write_W5500_SOCK_2Byte(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;

}

}

/*******************************************************************************

* 函数名 : Socket_Connect

* 描述 : 设置指定Socket(0~7)为客户端与远程服务器连接

* 输入 : s:待设定的端口

* 输出 : 无

* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)

* 说明 : 当本机Socket工作在客户端模式时,引用该程序,与远程服务器建立连接

*如果启动连接后出现超时中断,则与服务器连接失败,需要重新调用该程序连接

*该程序每调用一次,就与服务器产生一次连接

*******************************************************************************/

unsigned char Socket_Connect(SOCKET s)

{

Write_W5500_SOCK_1Byte(s,Sn_MR,MR_TCP);//设置socket为TCP模式

Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socket

Delay(5);//延时5ms

if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_INIT)//如果socket打开失败

{

Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socket

return FALSE;//返回FALSE(0x00)

}

Write_W5500_SOCK_1Byte(s,Sn_CR,CONNECT);//设置Socket为Connect模式

return TRUE;//返回TRUE,设置成功

}

/*******************************************************************************

* 函数名 : Socket_Listen

* 描述 : 设置指定Socket(0~7)作为服务器等待远程主机的连接

* 输入 : s:待设定的端口

* 输出 : 无

* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)

* 说明 : 当本机Socket工作在服务器模式时,引用该程序,等等远程主机的连接

*该程序只调用一次,就使W5500设置为服务器模式

*******************************************************************************/

unsigned char Socket_Listen(SOCKET s)

{

Write_W5500_SOCK_1Byte(s,Sn_MR,MR_TCP);//设置socket为TCP模式

Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socket

Delay(5);//延时5ms

if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_INIT)//如果socket打开失败

{

Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socket

return FALSE;//返回FALSE(0x00)

}

Write_W5500_SOCK_1Byte(s,Sn_CR,LISTEN);//设置Socket为侦听模式

Delay(5);//延时5ms

if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_LISTEN)//如果socket设置失败

{

Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//设置不成功,关闭Socket

return FALSE;//返回FALSE(0x00)

}

return TRUE;

//至此完成了Socket的打开和设置侦听工作,至于远程客户端是否与它建立连接,则需要等待Socket中断,

//以判断Socket的连接是否成功。参考W5500数据手册的Socket中断状态

//在服务器侦听模式不需要设置目的IP和目的端口号

}

/*******************************************************************************

* 函数名 : Socket_UDP

* 描述 : 设置指定Socket(0~7)为UDP模式

* 输入 : s:待设定的端口

* 输出 : 无

* 返回值 : 成功返回TRUE(0xFF),失败返回FALSE(0x00)

* 说明 : 如果Socket工作在UDP模式,引用该程序,在UDP模式下,Socket通信不需要建立连接

*该程序只调用一次,就使W5500设置为UDP模式

*******************************************************************************/

unsigned char Socket_UDP(SOCKET s)

{

Write_W5500_SOCK_1Byte(s,Sn_MR,MR_UDP);//设置Socket为UDP模式*/

Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socket*/

Delay(5);//延时5ms

if(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_UDP)//如果Socket打开失败

{

Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socket

return FALSE;//返回FALSE(0x00)

}

else

return TRUE;

//至此完成了Socket的打开和UDP模式设置,在这种模式下它不需要与远程主机建立连接

//因为Socket不需要建立连接,所以在发送数据前都可以设置目的主机IP和目的Socket的端口号

//如果目的主机IP和目的Socket的端口号是固定的,在运行过程中没有改变,那么也可以在这里设置

}

/*******************************************************************************

* 函数名 : W5500_Interrupt_Process

* 描述 : W5500中断处理程序框架

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : 无

*******************************************************************************/

void W5500_Interrupt_Process(void)

{

unsigned char i,j;

IntDispose:

i=Read_W5500_1Byte(SIR);//读取端口中断标志寄存器

if((i & S0_INT) == S0_INT)//Socket0事件处理

{

j=Read_W5500_SOCK_1Byte(0,Sn_IR);//读取Socket0中断标志寄存器

Write_W5500_SOCK_1Byte(0,Sn_IR,j);

if(j&IR_CON)//在TCP模式下,Socket0成功连接

{

S0_State|=S_CONN;//网络连接状态0x02,端口完成连接,可以正常传输数据

}

if(j&IR_DISCON)//在TCP模式下Socket断开连接处理

{

Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//关闭端口,等待重新打开连接

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连接或数据传输超时处理

{

Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);// 关闭端口,等待重新打开连接

S0_State=0;//网络连接状态0x00,端口连接失败

}

}

if(Read_W5500_1Byte(SIR) != 0)

goto IntDispose;

}

/*******************************************************************************

* 函数名 : NVIC_Configuration

* 描述 : STM32中断向量表配配置

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : 设置KEY1(PC11)的中断优先组

*******************************************************************************/

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC初始化结构体

/* Set the Vector Table base location at 0x08000000 */

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//设置中断优先级组为1,优先组(可设0~4位)

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//设置中断向量号

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//设置抢先优先级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//设置响应优先级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能NVIC

NVIC_Init(&NVIC_InitStructure);

}

/*******************************************************************************

* 函数名 : RCC_Configuration

* 描述 : 设置系统时钟为72MHZ(这个可以根据需要改)

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : STM32F107x和STM32F105x系列MCU与STM32F103x系列MCU时钟配置有所不同

*******************************************************************************/

void RCC_Configuration(void)

{

ErrorStatus HSEStartUpStatus; //外部高速时钟(HSE)的工作状态变量

RCC_DeInit(); //将所有与时钟相关的寄存器设置为默认值

RCC_HSEConfig(RCC_HSE_ON); //启动外部高速时钟HSE

HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待外部高速时钟(HSE)稳定

if(SUCCESS == HSEStartUpStatus) //如果外部高速时钟已经稳定

{

/* Enable Prefetch Buffer */

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Flash设置

/* Flash 2 wait state */

FLASH_SetLatency(FLASH_Latency_2);

RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置AHB时钟等于系统时钟(1分频)/72MHZ

RCC_PCLK2Config(RCC_HCLK_Div1); //设置APB2时钟和HCLK时钟相等/72MHz(最大为72MHz)

RCC_PCLK1Config(RCC_HCLK_Div2); //设置APB1时钟是HCLK时钟的2分频/36MHz(最大为36MHz)

#ifndef STM32F10X_CL //如果使用的不是STM32F107x或STM32F105x系列MCU,PLL以下配置

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //PLLCLK = 8MHz * 9 = 72 MHz

#else //如果使用的是STM32F107x或STM32F105x系列MCU,PLL以下配置

/***** 配置PLLx *****/

/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */

RCC_PREDIV2Config(RCC_PREDIV2_Div5);

RCC_PLL2Config(RCC_PLL2Mul_8);

RCC_PLL2Cmd(ENABLE); //使能PLL2

while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET);//等待PLL2稳定

/* PLL configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */

RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);

RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);

#endif

RCC_PLLCmd(ENABLE); //使能PLL

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL稳定

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //设置系统时钟的时钟源为PLL

while(RCC_GetSYSCLKSource() != 0x08); //检查系统的时钟源是否是PLL

RCC_ClockSecuritySystemCmd(ENABLE); //使能系统安全时钟

/* Enable peripheral clocks --------------------------------------------------*/

/* Enable I2C1 and I2C1 clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* Enable GPIOA GPIOB SPI1 and USART1 clocks */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB

| RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD

| RCC_APB2Periph_AFIO, ENABLE);

}

}

/*******************************************************************************

* 函数名 : Timer2_Init_Config

* 描述 : Timer2初始化配置

* 输入 : 无

* 输出 : 无

* 返回 : 无

* 说明 : 无

*******************************************************************************/

void Timer2_Init_Config(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能Timer2时钟

TIM_TimeBaseStructure.TIM_Period = 9;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值(计数到10为1ms)

TIM_TimeBaseStructure.TIM_Prescaler = 7199;//设置用来作为TIMx时钟频率除数的预分频值(10KHz的计数频率)

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置时钟分割:TDTS = TIM_CKD_DIV1

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM向上计数模式

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能TIM2指定的中断

TIM_Cmd(TIM2, ENABLE); //使能TIMx外设

}

/*******************************************************************************

* 函数名 : TIM2_IRQHandler

* 描述 : 定时器2中断断服务函数

* 输入 : 无

* 输出 : 无

* 返回 : 无

* 说明 : 无

*******************************************************************************/

void TIM2_IRQHandler(void)

{

if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)

{

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

Timer2_Counter++;

W5500_Send_Delay_Counter++;

}

}

/*******************************************************************************

* 函数名 : Delay

* 描述 : 延时函数(ms)

* 输入 : d:延时系数,单位为毫秒

* 输出 : 无

* 返回 : 无

* 说明 : 延时是利用Timer2定时器产生的1毫秒的计数来实现的

*******************************************************************************/

void Delay(unsigned int d)

{

Timer2_Counter=0;

while(Timer2_Counter < d);

}

/*******************************************************************************

* 函数名 : Delay

* 描述 : 延时函数(ms)

* 输入 : *data 数据指针

* length 字节数

* 输出 : 无

* 返回 : 无

*******************************************************************************/

void SendData(unsigned char *data,int length)

{

if(S0_State == (S_INIT|S_CONN))

{

S0_Data&=~S_TRANSMITOK;

memcpy(Tx_Buffer, data, length);

Write_SOCK_Data_Buffer(0, Tx_Buffer, length);

}

}

/*******************************************************************************

* 函数名 : MyW5500_Init

* 描述 : 集成化W5500初始函数

* 输出 : 无

* 返回 : 无

*******************************************************************************/

void My_W5500_Init(void)

{

RCC_Configuration();//设置系统时钟为72MHZ(这个可以根据需要改)

NVIC_Configuration();//STM32中断向量表配配置

SPI_Configuration();//W5500 SPI初始化配置(STM32 SPI1)

Timer2_Init_Config();//Timer2初始化配置

W5500_GPIO_Configuration();//W5500 GPIO初始化配置

/*Load_Net_Parameters*/

Gateway_IP[0] = GATEWAY_IP_0;//加载网关参数

Gateway_IP[1] = GATEWAY_IP_1;

Gateway_IP[2] = GATEWAY_IP_2;

Gateway_IP[3] = GATEWAY_IP_3;

Sub_Mask[0]=SUB_MASK_0;//加载子网掩码

Sub_Mask[1]=SUB_MASK_1;

Sub_Mask[2]=SUB_MASK_2;

Sub_Mask[3]=SUB_MASK_3;

Phy_Addr[0]=PHY_ADDR_0;//加载物理地址

Phy_Addr[1]=PHY_ADDR_1;

Phy_Addr[2]=PHY_ADDR_2;

Phy_Addr[3]=PHY_ADDR_3;

Phy_Addr[4]=PHY_ADDR_4;

Phy_Addr[5]=PHY_ADDR_5;

IP_Addr[0]=IP_ADDR_0;//加载本机IP地址

IP_Addr[1]=IP_ADDR_1;

IP_Addr[2]=IP_ADDR_2;

IP_Addr[3]=IP_ADDR_3;

S0_Port[0] = S0_PORT_0;//加载端口0的端口号5000

S0_Port[1] = S0_PORT_1;

UDP_DIPR[0] = UDP_DIR_0;//UDP(广播)模式,目的主机IP地址

UDP_DIPR[1] = UDP_DIR_1;

UDP_DIPR[2] = UDP_DIR_2;

UDP_DIPR[3] = UDP_DIR_3;

UDP_DPORT[0] = UDP_DPORT_0;//UDP(广播)模式,目的主机端口号

UDP_DPORT[1] = UDP_DPORT_1;

S0_Mode=UDP_MODE;//加载端口0的工作模式,UDP模式

W5500_Hardware_Reset();

W5500_Init();//初始化W5500寄存器函数

Detect_Gateway();//检查网关服务器

Socket_Init(0);//指定Socket(0~7)初始化,初始化端口0

}

/*******************************************************************************

* 函数名 : W5500_Socket_Set

* 描述 : W5500端口初始化配置

* 输入 : 无

* 输出 : 无

* 返回值 : 无

* 说明 : 分别设置4个端口,根据端口工作模式,将端口置于TCP服务器、TCP客户端或UDP模式.

*从端口状态字节Socket_State可以判断端口的工作情况

*******************************************************************************/

void W5500_Socket_Set(void)

{

if(S0_State==0)//端口0初始化配置

{

if(S0_Mode==TCP_SERVER)//TCP服务器模式

{

if(Socket_Listen(0)==TRUE)

S0_State=S_INIT;

else

S0_State=0;

}

else if(S0_Mode==TCP_CLIENT)//TCP客户端模式

{

if(Socket_Connect(0)==TRUE)

S0_State=S_INIT;

else

S0_State=0;

}

else//UDP模式

{

if(Socket_UDP(0)==TRUE)

S0_State=S_INIT|S_CONN;

else

S0_State=0;

}

}

}

/*******************************************************************************

* 函数名 : Process_Socket_Data

* 描述 : W5500接收并发送接收到的数据

* 输入 : s:端口号

* 输出 : 无

* 返回值 : 无

* 说明 : 本过程先调用S_rx_process()从W5500的端口接收数据缓冲区读取数据,

*然后将读取的数据从Rx_Buffer拷贝到Temp_Buffer缓冲区进行处理。

*处理完毕,将数据从Temp_Buffer拷贝到Tx_Buffer缓冲区。调用S_tx_process()

*发送数据。

*******************************************************************************/

void Process_Socket_Data(SOCKET s)

{

unsigned short size;

size=Read_SOCK_Data_Buffer(s, Rx_Buffer);

memcpy(Tx_Buffer, Rx_Buffer+8, size-8);

Write_SOCK_Data_Buffer(s, Tx_Buffer, size);

}

使用方法

W5500_Socket_Set(); //W5500端口初始化

W5500_Interrupt_Process(); //W5500中断处理程序框架

if((S0_Data & S_RECEIVE) == S_RECEIVE) //如果Socket0接收到数据

{

S0_Data&=~S_RECEIVE;

Read_SOCK_Data_Buffer(0, Rx_Buffer); //读取数据,返回值为数据长度

}

注意Rx_Buffer[0]~Rx_Buffer[7]为地址头(具体可参照UDP协议),真正的数据从Rx_Buffer[8]开始


版权声明:本文为weixin_39752788原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。