当前位置:首页 > 芯闻号 > 充电吧
[导读]#ifndef _W5500_QUEUE_H_ #define _W5500_QUEUE_H_ #include "type.h" #define W5500_FRAME_SIZE        

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

  }
}


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭