STM32驱动W5100实现udp通信
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:WIN7
开发环境:MDK4.72
MCU:STM32F103ZE
源代码:
驱动层代码:
drv_w5100.h
/*********************************************************************
* w5100驱动层头文件
* (c)copyright 2013,jdh
* All Right Reserved
*文件名:drv_w5100.h
*程序员:jdh
*修改日期:2013/10/22
* 2013/10/23
* 2013/10/24
**********************************************************************/
/*********************************************************************
硬件连接说明
电路标号 单片机引脚 特殊功能
W5100_MISO PB4 SPI3_MISO
W5100_MOSI PB5 SPI3_MOSI
W5100_CS PA15 SPI3_NSS
W5100_SCLK PB3 SPI3_SCK
/RESET PD3
/INT PD6
**********************************************************************/
#ifndef _DRV_W5100_H_
#define _DRV_W5100_H_
/*********************************************************************
* 头文件
**********************************************************************/
#include "stm32f10x.h"
#include "stm32f10x_spi.h"
/*********************************************************************
* 宏定义
**********************************************************************/
/*********************************************************************
* 读写操作
**********************************************************************/
//写操作
#define WRITE_COMMAND 0xf0
//读操作
#define READ_COMMAND 0x0f
/*********************************************************************
* 基地址
**********************************************************************/
#define COMMON_BASE 0x0000
/*********************************************************************
* 寄存器
**********************************************************************/
//-----------------------------------------------------------------------------
// Common register
//-----------------------------------------------------------------------------
//Mode register, R/W, Default=0x00
#define SOCKET0 0
#define SOCKET1 1
#define SOCKET2 2
#define SOCKET3 3
#define TCP_SERVER 0
#define TCP_CLIENT 1
#define UDP 2
#define W5100_MODE COMMON_BASE
#define MODE_RST 0x80 //Software reset
#define MODE_PB 0x10 //Ping block mode
#define MODE_PPPOE 0x08 //PPOE mode
#define MODE_AI 0x02 //Address auto increment in indirect bus I/F
#define MODE_IND 0x01 //Indirect bus I/F mode
//Gateway address register, R/W, default=0x00
#define W5100_GAR COMMON_BASE+0x01
//Subnet mask address, R/W, default=0x00
#define W5100_SUBR COMMON_BASE+0x05
//Source hardware address, R/W, default=0x00
#define W5100_SHAR COMMON_BASE+0x09
//Source IP address, R/W, default=0x00
#define W5100_SIPR COMMON_BASE+0x0f
//Interrupt and interrupt mask register
#define W5100_IR COMMON_BASE+0x15 //RO, Default=0x00
#define IR_CONFLICT 0x80 //IP conflict
#define IR_UNREACH 0x40 //Destination unreachable
#define IR_PPPOE 0x20 //PPOE close
#define IR_S3_INT 0x08 //Occurrence of socket 3 socket interrupt
#define IR_S2_INT 0x04 //Occurrence of socket 2 socket interrupt
#define IR_S1_INT 0x02 //Occurrence of socket 1 socket interrupt
#define IR_S0_INT 0x01 //Occurrence of socket 0 socket interrupt
#define W5100_IMR COMMON_BASE+0x16 //R/W, Default=0x00
#define IMR_CONFLICT 0x80 //IP conflict
#define IMR_UNREACH 0x40 //Destination unreachable
#define IMR_PPPOE 0x20 //PPOE close
#define IMR_S3_INT 0x08 //Occurrence of socket 3 socket interrupt
#define IMR_S2_INT 0x04 //Occurrence of socket 2 socket interrupt
#define IMR_S1_INT 0x02 //Occurrence of socket 1 socket interrupt
#define IMR_S0_INT 0x01 //Occurrence of socket 0 socket interrupt
//Retry time value. Value 1 means 100us, R/W, default=0x07D0
#define W5100_RTR COMMON_BASE+0x17
//Retry count, R/W, Default=0x08
#define W5100_RCR COMMON_BASE+0X19
//RX memory size register, R/W, default=0x55
//-------------------------------------------------------- S1 S0 Memory size
// Socket3 | Socket2 | Socket1 | Socket0 | 0 0 1KB
//-------------|-------------|-------------|-------------| 0 1 2KB
//S1 S0 |S1 S0 |S1 S0 |S1 S0 | 1 0 4KB
//-------------------------------------------------------- 1 1 8KB
#define W5100_RMSR COMMON_BASE+0x1a
//TX memory size register, R/W, default=0x55
#define W5100_TMSR COMMON_BASE+0x1b
//Authentication type in PPPOE mode, R, default=0x0000
#define W5100_PATR COMMON_BASE+0x1c
//PPP LCP request timer register, R/W, default=0x28
//Value 1 is about 25ms
#define W5100_PTIMER COMMON_BASE+0x28
//PPP LCP magic number register, R/W, default=0x00
#define W5100_PMAGIC COMMON_BASE+0x29
//Unreachable IP address, RO, default=0x00
#define W5100_UIPR COMMON_BASE+0x2a
//Unreachable port register, RO, default=0x0000
#define W5100_UPORT COMMON_BASE+0x2e
//-----------------------------------------------------------------------------
// Socket register
//-----------------------------------------------------------------------------
//Socket mode register, R/W, default=0x00
#define W5100_S0_MR COMMON_BASE+0x0400 //Socket 0
#define W5100_S1_MR COMMON_BASE+0x0500 //Socket 1
#define W5100_S2_MR COMMON_BASE+0x0600 //Socket 2
#define W5100_S3_MR COMMON_BASE+0x0700 //Socket 3
#define S_MR_MULTI 0x80 //Multcasting
#define S_MR_MC 0x20 //Multcast
// P3 P2 P1 P0 Meaning
#define S_MR_CLOSED 0x00 // 0 0 0 0 Closed
#define S_MR_TCP 0x01 // 0 0 0 1 TCP
#define S_MR_UDP 0x02 // 0 0 1 0 UDP
#define S_MR_IPRAW 0x03 // 0 0 1 1 IPRAW
#define S_MR_MACRAW 0x04 // 0 1 0 0 MACRAW
#define S_MR_PPPOE 0x05 // 0 1 0 1 PPPOE
//Socket command register, R/W, default=0x00
#define W5100_S0_CR COMMON_BASE+0x0401 //Socket 0
#define W5100_S1_CR COMMON_BASE+0x0501 //Socket 1
#define W5100_S2_CR COMMON_BASE+0x0601 //Socket 2
#define W5100_S3_CR COMMON_BASE+0x0701 //Socket 3
#define S_CR_OPEN 0x01 //It is used to initialize the socket
#define S_CR_LISTEN 0x02 //In TCP mode, it waits for a connection request from any remote peer(Client)
#define S_CR_CONNECT 0x04 //In TCP mode, it sends a connection request to remote peer(SERVER)
#define S_CR_DISCON 0x08 //In TCP mode, it sends a connection termination request
#define S_CR_CLOSE 0x10 //Used to close the socket
#define S_CR_SEND 0x20 //It transmit the data as much as the increase size of write pointer
#define S_CR_SEND_MAC 0x21 //In UDP mode, same as SEND
#define S_CR_SEND_KEEP 0x22 //In TCP mode
#define S_CR_RECV 0x40 //Receiving is processed including the value of socket RX read
//pointer register
/* Definition for PPPOE */
#define S_CR_PCON 0x23 //Start of ADSL connection
#define S_CR_PDISCON 0x24 //End of ADSL connection
#define S_CR_PCR 0x25 //Send REQ message ineach phase
#define S_CR_PCN 0x26 //Send NAK message in each phase
#define S_CR_PCJ 0x27 //Senf REJECT message in each phase
//Socket interrup register, RO, default=0x00
#define W5100_S0_IR COMMON_BASE+0x0402 //Socket 0
#define W5100_S1_IR COMMON_BASE+0x0502 //Socket 1
#define W5100_S2_IR COMMON_BASE+0x0602 //Socket 2
#define W5100_S3_IR COMMON_BASE+0x0702 //Socket 3
#define S_IR_SENDOK 0x10 //Send data complete
#define S_IR_TIMEOUT 0x08 //Set if timeout occurs during connection or termination
//or data transmission
#define S_IR_RECV 0x04 //Set if data is received
#define S_IR_DISCON 0x02 //Set if receiv connection termination request
#define S_IR_CON 0x01 //Set if connetion is established
/* Definition for PPPOE */
#define S_IR_PRECV 0x80 //Indicate receiving no support option data
#define S_IR_PFAIL 0x40 //Indicate PAP Authentication fail
#define S_IR_PNEXT 0x20 //Go next phase
//Socket status register, RO, default=0x00
#define W5100_S0_SSR COMMON_BASE+0x0403 //Socket 0
#define W5100_S1_SSR COMMON_BASE+0x0503 //Socket 1
#define W5100_S2_SSR COMMON_BASE+0x0603 //Socket 2
#define W5100_S3_SSR COMMON_BASE+0x0703 //Socket 3
#define S_SSR_CLOSED 0x00 //In case that OPEN command are given to Sn_CR, Timeout interrupt
//is asserted or connection is terminated
#define S_SSR_INIT 0x13 //In case that Sn_MR is set as TCP and OPEN commands are given to Sn_CR
#define S_SSR_LISTEN 0x14 //In case that under the SOCK_INIT status, LISTEN commands
//are given to Sn_CR
#define S_SSR_ESTABLISHED 0x17 //In case that connection is established
#define S_SSR_CLOSE_WAIT 0x1c //In case that connection temination request is received
#define S_SSR_UDP 0x22 //In case that OPEN command is given to Sn_CR when Sn_MR is set as UDP
#define S_SSR_IPRAW 0x32 //In case that OPEN command is given to Sn_CR when Sn_MR is set as IPRAW
#define S_SSR_MACRAW 0x42 //In case that OPEN command is given to S0_CR when S0_MR is set as MACRAW
#define S_SSR_PPPOE 0x5f //In case that OPEN command is given to S0_CR when S0_MR is set as PPPOE
//Below is shown in the status change, and does not need much attention
#define S_SSR_SYNSEND 0x15
#define S_SSR_SYNRECV 0x16
#define S_SSR_FIN_WAIT 0x18
#define S_SSR_CLOSING 0x1a
#define S_SSR_TIME_WAIT 0x1b
#define S_SSR_LAST_ACK 0x1d
#define S_SSR_ARP0 0x11
#define S_SSR_ARP1 0x21
#define S_SSR_ARP2 0x31
//Socket Source port register, R/W, default=0x00
#define W5100_S0_PORT COMMON_BASE+0x0404 //Socket 0
#define W5100_S1_PORT COMMON_BASE+0x0504 //Socket 1
#define W5100_S2_PORT COMMON_BASE+0x0604 //Socket 2
#define W5100_S3_PORT COMMON_BASE+0x0704 //Socket 3
//Socket destination hardware address register, R/W, default=0x00
#define W5100_S0_DHAR COMMON_BASE+0x0406 //Socket 0
#define W5100_S1_DHAR COMMON_BASE+0x0506 //Socket 1
#define W5100_S2_DHAR COMMON_BASE+0x0606 //Socket 2
#define W5100_S3_DHAR COMMON_BASE+0x0706 //Socket 3
//Socket destination IP address register, R/W, default=0x00
#define W5100_S0_DIPR COMMON_BASE+0x040c //Socket 0
#define W5100_S1_DIPR COMMON_BASE+0x050c //Socket 1
#define W5100_S2_DIPR COMMON_BASE+0x060c //Socket 2
#define W5100_S3_DIPR COMMON_BASE+0x070c //Socket 3
//Socket destionation port register, R/W, default=0x00
#define W5100_S0_DPORT COMMON_BASE+0x0410 //Socket 0
#define W5100_S1_DPORT COMMON_BASE+0x0510 //Socket 1
#define W5100_S2_DPORT COMMON_BASE+0x0610 //Socket 2
#define W5100_S3_DPORT COMMON_BASE+0x0710 //Socket 3
//Socket maximum segment size register, R/W, default=0x00
#define W5100_S0_MSS COMMON_BASE+0x0412 //Socket 0
#define W5100_S1_MSS COMMON_BASE+0x0512 //Socket 1
#define W5100_S2_MSS COMMON_BASE+0x0612 //Socket 2
#define W5100_S3_MSS COMMON_BASE+0x0712 //Socket 3
//Socket IP protocol register, R/W, default=0x00
//See http://www.iana.org/assignments/protocol-number
#define W5100_S0_PROTO COMMON_BASE+0x0414 //Socket 0
#define W5100_S1_PROTO COMMON_BASE+0x0514 //Socket 1
#define W5100_S2_PROTO COMMON_BASE+0x0614 //Socket 2
#define W5100_S3_PROTO COMMON_BASE+0x0714 //Socket 3
//Socket IP type of servce register, R/W, default=0x00
#define W5100_S0_TOS COMMON_BASE+0x0415 //Socket 0
#define W5100_S1_TOS COMMON_BASE+0x0515 //Socket 1
#define W5100_S2_TOS COMMON_BASE+0x0615 //Socket 2
#define W5100_S3_TOS COMMON_BASE+0x0715 //Socket 3
//Socket IP time to live register, R/W, default=0x80
#define W5100_S0_TTL COMMON_BASE+0x0416 //Socket 0
#define W5100_S1_TTL COMMON_BASE+0x0516 //Socket 1
#define W5100_S2_TTL COMMON_BASE+0x0616 //Socket 2
#define W5100_S3_TTL COMMON_BASE+0x0716 //Socket 3
//Socket TX free size register, RO, default=0x0800
//should read upper byte first and lower byte later
#define W5100_S0_TX_FSR COMMON_BASE+0x0420 //Socket 0
#define W5100_S1_TX_FSR COMMON_BASE+0x0520 //Socket 1
#define W5100_S2_TX_FSR COMMON_BASE+0x0620 //Socket 2
#define W5100_S3_TX_FSR COMMON_BASE+0x0720 //Socket 3
//Socket TX read pointer register, RO, default=0x0000
//should read upper byte first and lower byte later
#define W5100_S0_TX_RR COMMON_BASE+0x0422 //Socket 0
#define W5100_S1_TX_RR COMMON_BASE+0x0522 //Socket 1
#define W5100_S2_TX_RR COMMON_BASE+0x0622 //Socket 2
#define W5100_S3_TX_RR COMMON_BASE+0x0722 //Socket 3
//Socket TX write pointer register, R/W, default=0x0000
//should read upper byte first and lower byte later
#define W5100_S0_TX_WR COMMON_BASE+0x0424 //Socket 0
#define W5100_S1_TX_WR COMMON_BASE+0x0524 //Socket 1
#define W5100_S2_TX_WR COMMON_BASE+0x0624 //Socket 2
#define W5100_S3_TX_WR COMMON_BASE+0x0724 //Socket 3
//Socket RX size register, RO, default=0x0000
//should read upper byte first and lower byte later
#define W5100_S0_RX_RSR COMMON_BASE+0x0426 //Socket 0
#define W5100_S1_RX_RSR COMMON_BASE+0x0526 //Socket 1
#define W5100_S2_RX_RSR COMMON_BASE+0x0626 //Socket 2
#define W5100_S3_RX_RSR COMMON_BASE+0x0726 //Socket 3
//Socket RX read pointer register, R/W, default=0x0000
//should read upper byte first and lower byte later
#define W5100_S0_RX_RR COMMON_BASE+0x0428 //Socket 0
#define W5100_S1_RX_RR COMMON_BASE+0x0528 //Socket 1
#define W5100_S2_RX_RR COMMON_BASE+0x0628 //Socket 2
#define W5100_S3_RX_RR COMMON_BASE+0x0728 //Socket 3
//Socket RX read pointer register, R/W, default=0x0000
//should read upper byte first and lower byte later
#define W5100_S0_RX_WR COMMON_BASE+0x042A //Socket 0
#define W5100_S1_RX_WR COMMON_BASE+0x052A //Socket 1
#define W5100_S2_RX_WR COMMON_BASE+0x062A //Socket 2
#define W5100_S3_RX_WR COMMON_BASE+0x072A //Socket 3
//TX memory
#define W5100_TX COMMON_BASE+0x4000
//RX memory
#define W5100_RX COMMON_BASE+0x6000
/*********************************************************************
* 数据结构
**********************************************************************/
/*********************************************************************
* 缓冲区结构
**********************************************************************/
struct _W5100_Buf
{
//缓冲区大小,单位字节
uint16_t size;
//基地址
uint16_t base_addr;
//屏蔽地址
uint16_t mask_addr;
};
/*********************************************************************
* 全局变量声明
**********************************************************************/
/*********************************************************************
* 发送缓存区参数
**********************************************************************/
extern struct _W5100_Buf W5100_Tx_Buf[4];
/*********************************************************************
* 接收缓存区参数
**********************************************************************/
extern struct _W5100_Buf W5100_Rx_Buf[4];
/*********************************************************************
* 函数
**********************************************************************/
/*********************************************************************
* 初始化w5100
*参数:ip:本机ip,4字节
* mac:本机mac,6字节
* submask:掩码:4字节
* gateway:网关,4字节
* socket_tx_size:socket发送缓存大小,4字节
* socket_rx_size:socket接收缓存大小,4字节
**********************************************************************/
void drv_w5100_init(uint8_t *ip,uint8_t *mac,uint8_t *submask,uint8_t *gateway,\
uint8_t *socket_tx_size,uint8_t *socket_rx_size);
/*********************************************************************
* 初始化io
*说明:初始化/INT和/RESET引脚
**********************************************************************/
void drv_w5100_init_io(void);
/*********************************************************************
* 初始化spi
**********************************************************************/
void drv_w5100_init_spi(void);
/*********************************************************************
* 初始化中断
**********************************************************************/
void drv_w5100_init_irq(void);
/*********************************************************************
* 复位w5100
**********************************************************************/
void drv_w5100_reset(void);
/*********************************************************************
* 使能芯片
*参数:enable:1使能,0关闭
**********************************************************************/
void drv_w5100_enable(uint8_t enable);
/*********************************************************************
* spi口发送一个字节
*参数:byte:发送的字节
*返回:收到的字节
**********************************************************************/
uint8_t drv_w5100_spi_tx_byte(uint8_t byte);
/*********************************************************************
* w5100写入一个字节
*参数:addr:地址
* byte:字节
**********************************************************************/
void drv_w5100_tx_byte(uint16_t addr,uint8_t byte);
/*********************************************************************
* w5100写缓存
*参数:addr:w5100缓存开始地址
* buf:缓存区地址
* len:缓存长度
**********************************************************************/
void drv_w5100_tx_buf(uint16_t addr,uint8_t *buf,uint16_t len);
/*********************************************************************
* w5100读取一个字节
*参数:addr:地址
*返回:读取的字节
**********************************************************************/
uint8_t drv_w5100_rx_byte(uint16_t addr);
/*********************************************************************
* w5100读取缓存
*参数:addr:w5100缓存开始地址
* buf:读取存放的缓存区地址
* len:读取长度
**********************************************************************/
void drv_w5100_rx_buf(uint16_t addr,uint8_t *buf,uint16_t len);
/*********************************************************************
* w5100设置网关
*参数:addr:需要设置的网关,4字节
**********************************************************************/
void drv_w5100_set_gateway(uint8_t *addr);
/*********************************************************************
* 读取w5100网关
*参数:addr:读取的网关存放地址,4字节长度
**********************************************************************/
void drv_w5100_get_gateway(uint8_t *addr);
/*********************************************************************
* w5100设置子网掩码
*参数:addr:需要设置的子网掩码,4字节
**********************************************************************/
void drv_w5100_set_submask(uint8_t *addr);
/*********************************************************************
* 读取w5100子网掩码
*参数:addr:读取的子网掩码,4字节
**********************************************************************/
void drv_w5100_get_submask(uint8_t *addr);
/*********************************************************************
* w5100设置mac地址
*参数:mac:需要设置的mac,6字节
**********************************************************************/
void drv_w5100_set_mac(uint8_t *mac);
/*********************************************************************
* 读取w5100的mac地址
*参数:addr:读取mac地址,6字节
**********************************************************************/
void drv_w5100_get_mac(uint8_t *mac);
/*********************************************************************
* w5100设置本机ip
*参数:ip:需要设置的ip,4字节
**********************************************************************/
void drv_w5100_set_ip(uint8_t *ip);
/*********************************************************************
* 读取w5100的ip地址
*参数:addr:读取ip地址,4字节
**********************************************************************/
void drv_w5100_get_ip(uint8_t *ip);
/*********************************************************************
* w5100设置端口的端口号
*参数:socket:端口:0-3
* port:端口号
**********************************************************************/
void drv_w5100_set_socket_port(uint8_t socket,uint16_t port);
/*********************************************************************
* 读取w5100端口的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t drv_w5100_get_socket_port(uint8_t socket);
/*********************************************************************
* w5100设置端口的目的mac地址
*参数:socket:端口:0-3
* mac:需要设置的mac,6字节
**********************************************************************/
void drv_w5100_set_socket_mac(uint8_t socket,uint8_t *mac);
/*********************************************************************
* 读取w5100端口的目的mac地址
*参数:socket:端口:0-3
* mac:读取的目的mac,6字节
**********************************************************************/
void drv_w5100_get_socket_mac(uint8_t socket,uint8_t *mac);
/*********************************************************************
* w5100设置端口的目的ip地址
*参数:socket:端口:0-3
* ip:需要设置的ip,4字节
**********************************************************************/
void drv_w5100_set_socket_dst_ip(uint8_t socket,uint8_t *ip);
/*********************************************************************
* 读取w5100端口的目的ip地址
*参数:socket:端口:0-3
* ip:读取的目的ip,4字节
**********************************************************************/
void drv_w5100_get_socket_dst_ip(uint8_t socket,uint8_t *ip);
/*********************************************************************
* w5100设置端口的目的端口号
*参数:socket:端口:0-3
* port:目的端口号
**********************************************************************/
void drv_w5100_set_socket_dst_port(uint8_t socket,uint16_t port);
/*********************************************************************
* 读取w5100端口的目的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t drv_w5100_get_socket_dst_port(uint8_t socket);
/*********************************************************************
* 设置w5100端口缓存大小
*说明:4个端口发送总缓存为8KB,接收总缓存为8KB
*参数:tx_size:发送缓存大小数组,4字节长度,值只能取1,2,4,8这4个.单位为KB
* rx_size:发送缓存大小数组,4字节长度,值只能取1,2,4,8这4个.单位为KB
**********************************************************************/
void drv_w5100_set_socket_buf_size(uint8_t *tx_size,uint8_t *rx_size);
/*********************************************************************
* 读取w5100端口的发送存储器剩余空间寄存器
*参数:socket:端口:0-3
*返回:发送存储器剩余空间
**********************************************************************/
uint16_t drv_w5100_get_socket_tx_fsr(uint8_t socket);
/*********************************************************************
* 读取w5100端口的接收数据字节数寄存器
*参数:socket:端口:0-3
*返回:接收数据字节数
**********************************************************************/
uint16_t drv_w5100_get_socket_rx_rsr(uint8_t socket);
/*********************************************************************
* 读取w5100端口接收的数据
*参数:socket:端口:0-3
* buf:接收的数据存放的缓存
* len:读取接收数据长度
**********************************************************************/
//void drv_w5100_socket_rx(uint8_t socket,uint8_t *buf,uint16_t len);
/*********************************************************************
* 读取w5100端口接收的数据
*参数:socket:端口:0-3
* buf:接收的数据存放的缓存
* len:读取接收数据长度
* ip:接收数据的ip
* port:接收数据的端口
**********************************************************************/
void drv_w5100_socket_rx(uint8_t socket,uint8_t *buf,uint16_t len,uint8_t *ip,uint16_t *port);
/*********************************************************************
* w5100端口发送数据
*参数:socket:端口:0-3
* buf:发送的数据存放的缓存
* len:发送数据长度
**********************************************************************/
void drv_w5100_socket_tx(uint8_t socket,uint8_t *buf,uint16_t len);
#endif
/*********************************************************************
* w5100驱动层文件
* (c)copyright 2013,jdh
* All Right Reserved
*文件名:drv_w5100.c
*程序员:jdh
*修改日期:2013/10/22
* 2013/10/23
* 2013/10/24
**********************************************************************/
/*********************************************************************
* 头文件
**********************************************************************/
#include "drv_w5100.h"
#include "drv_delay.h"
/*********************************************************************
* 全局变量定义
**********************************************************************/
/*********************************************************************
* 发送缓存区参数
**********************************************************************/
struct _W5100_Buf W5100_Tx_Buf[4];
/*********************************************************************
* 接收缓存区参数
**********************************************************************/
struct _W5100_Buf W5100_Rx_Buf[4];
/*********************************************************************
* 函数
**********************************************************************/
/*********************************************************************
* 初始化w5100
*参数:ip:本机ip,4字节
* mac:本机mac,6字节
* submask:掩码:4字节
* gateway:网关,4字节
* socket_tx_size:socket发送缓存大小,4字节
* socket_rx_size:socket接收缓存大小,4字节
**********************************************************************/
void drv_w5100_init(uint8_t *ip,uint8_t *mac,uint8_t *submask,uint8_t *gateway,\
uint8_t *socket_tx_size,uint8_t *socket_rx_size)
{
uint8_t value = 0;
//初始化IO
drv_w5100_init_io();
//SPI初始化
drv_w5100_init_spi();
//中断初始化
drv_w5100_init_irq();
//复位w5100
drv_w5100_reset();
//软复位
drv_w5100_tx_byte(W5100_MODE,MODE_RST);
drv_delay_ms(300);
//设置ip
drv_w5100_set_ip(ip);
//设置mac
drv_w5100_set_mac(mac);
//设置掩码
drv_w5100_set_submask(submask);
//设置网关
drv_w5100_set_gateway(gateway);
//端口缓存设置
drv_w5100_set_socket_buf_size(socket_tx_size,socket_rx_size);
//设置中断
value = drv_w5100_rx_byte(W5100_IMR);
value |= IMR_CONFLICT | IMR_UNREACH | \
IMR_S0_INT | IMR_S1_INT | IMR_S2_INT | IMR_S3_INT;
drv_w5100_tx_byte(W5100_IMR,value);
}
/*********************************************************************
* 初始化io
*说明:初始化/INT和/RESET引脚
**********************************************************************/
void drv_w5100_init_io(void)
{
//定义IO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
//初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
//管脚初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
//选择GPIO响应速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//设置为输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//初始化
GPIO_Init(GPIOD, &GPIO_InitStructure);
//初始化时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
//管脚初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
//选择GPIO响应速度
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//设置为输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//初始化
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/*********************************************************************
* 初始化spi
**********************************************************************/
void drv_w5100_init_spi(void)
{
//定义IO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure ;
//定义SPI初始化结构体
SPI_InitTypeDef SPI_InitStructure ;
//配置其他引脚
//配置CS
//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE ) ;
//配置SPI引脚CSN
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init( GPIOA, &GPIO_InitStructure );
//PA15默认是JTDI脚,重映射关闭JTDI功能
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
//关闭w5100
drv_w5100_enable(0);
drv_w5100_enable(1);
drv_w5100_enable(0);
//初始化SPI
//关闭SPI
SPI_Cmd(SPI3,DISABLE);
//初始化SPI时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,ENABLE);
//设置IO口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
//配置SPI3引脚:SCK, MISO and MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init( GPIOB, &GPIO_InitStructure );
// SPI配置
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波特率分频设置:72M-18M,64M-16M
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4 ;
//SPI设置成LSB模式
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB ;
SPI_InitStructure.SPI_CRCPolynomial = 7 ;
SPI_Init( SPI3, &SPI_InitStructure ) ;
//启动SPI
SPI_Cmd(SPI3,ENABLE);
}
/*********************************************************************
* 初始化中断
**********************************************************************/
void drv_w5100_init_irq(void)
{
//定义中断结构体
NVIC_InitTypeDef NVIC_InitStructure ;
//定义外部中断结构体
EXTI_InitTypeDef EXTI_InitStructure;
//初始化中断脚PD6时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//配置中断源为PD6
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource6);
// 配置EXTI_Line6下降沿触发
EXTI_ClearITPendingBit(EXTI_Line6);
EXTI_InitStructure.EXTI_Line = EXTI_Line6;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//打开NTRX中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //通道设置为外部中断线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //中断抢占先等级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //中断响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断
NVIC_Init(&NVIC_InitStructure); //初始化
//清中断
//EXTI_ClearITPendingBit(EXTI9_5_IRQn);
//EXTI_Line0中断允许
//EXTI_GenerateSWInterrupt(EXTI_Line6);
}
/*********************************************************************
* 复位w5100
**********************************************************************/
void drv_w5100_reset(void)
{
GPIO_ResetBits(GPIOD,GPIO_Pin_3);
drv_delay_ms(20);
GPIO_SetBits(GPIOD,GPIO_Pin_3);
}
/*********************************************************************
* 使能芯片
*参数:enable:1使能,0关闭
**********************************************************************/
void drv_w5100_enable(uint8_t enable)
{
if (enable)
{
//使能
GPIO_ResetBits(GPIOA,GPIO_Pin_15);
}
else
{
//关闭
GPIO_SetBits(GPIOA,GPIO_Pin_15);
}
}
/*********************************************************************
* spi口发送一个字节
*参数:byte:发送的字节
*返回:收到的字节
**********************************************************************/
uint8_t drv_w5100_spi_tx_byte(uint8_t byte)
{
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI3,byte);
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI3);
}
/*********************************************************************
* w5100写入一个字节
*参数:addr:地址
* byte:字节
**********************************************************************/
void drv_w5100_tx_byte(uint16_t addr,uint8_t byte)
{
//使能w5100
drv_w5100_enable(1);
drv_w5100_spi_tx_byte(WRITE_COMMAND);
drv_w5100_spi_tx_byte(addr / 256);
drv_w5100_spi_tx_byte(addr % 256);
drv_w5100_spi_tx_byte(byte);
//关闭w5100
drv_w5100_enable(0);
}
/*********************************************************************
* w5100写缓存
*参数:addr:w5100缓存开始地址
* buf:缓存区地址
* len:缓存长度
**********************************************************************/
void drv_w5100_tx_buf(uint16_t addr,uint8_t *buf,uint16_t len)
{
uint16_t i;
for (i = 0; i < len; i++)
{
drv_w5100_tx_byte(addr + i,*buf++);
}
}
/*********************************************************************
* w5100读取一个字节
*参数:addr:地址
*返回:读取的字节
**********************************************************************/
uint8_t drv_w5100_rx_byte(uint16_t addr)
{
uint8_t byte = 0;
//使能w5100
drv_w5100_enable(1);
drv_w5100_spi_tx_byte(READ_COMMAND);
drv_w5100_spi_tx_byte(addr / 256);
drv_w5100_spi_tx_byte(addr % 256);
byte = drv_w5100_spi_tx_byte(0);
//关闭w5100
drv_w5100_enable(0);
return byte;
}
/*********************************************************************
* w5100读取缓存
*参数:addr:w5100缓存开始地址
* buf:读取存放的缓存区地址
* len:读取长度
**********************************************************************/
void drv_w5100_rx_buf(uint16_t addr,uint8_t *buf,uint16_t len)
{
uint16_t i;
for (i = 0; i < len; i++)
{
*buf++ = drv_w5100_rx_byte(addr++);
}
}
/*********************************************************************
* w5100设置网关
*参数:addr:需要设置的网关,4字节
**********************************************************************/
void drv_w5100_set_gateway(uint8_t *addr)
{
uint8_t i = 0;
for (i = 0;i < 4;i++)
{
drv_w5100_tx_byte(W5100_GAR + i,addr[i]);
}
}
/*********************************************************************
* 读取w5100网关
*参数:addr:读取的网关存放地址,4字节长度
**********************************************************************/
void drv_w5100_get_gateway(uint8_t *addr)
{
uint8_t i = 0;
for (i = 0;i < 4;i++)
{
addr[i] = drv_w5100_rx_byte(W5100_GAR + i);
}
}
/*********************************************************************
* w5100设置子网掩码
*参数:addr:需要设置的子网掩码,4字节
**********************************************************************/
void drv_w5100_set_submask(uint8_t *addr)
{
uint8_t i = 0;
for (i = 0;i < 4;i++)
{
drv_w5100_tx_byte(W5100_SUBR + i,addr[i]);
}
}
/*********************************************************************
* 读取w5100子网掩码
*参数:addr:读取的子网掩码,4字节
**********************************************************************/
void drv_w5100_get_submask(uint8_t *addr)
{
uint8_t i = 0;
for (i = 0;i < 4;i++)
{
addr[i] = drv_w5100_rx_byte(W5100_SUBR + i);
}
}
/*********************************************************************
* w5100设置mac地址
*参数:mac:需要设置的mac,6字节
**********************************************************************/
void drv_w5100_set_mac(uint8_t *mac)
{
uint8_t i = 0;
for (i = 0;i < 6;i++)
{
drv_w5100_tx_byte(W5100_SHAR + i,mac[i]);
}
}
/*********************************************************************
* 读取w5100的mac地址
*参数:addr:读取mac地址,6字节
**********************************************************************/
void drv_w5100_get_mac(uint8_t *mac)
{
uint8_t i = 0;
for (i = 0;i < 6;i++)
{
mac[i] = drv_w5100_rx_byte(W5100_SHAR + i);
}
}
/*********************************************************************
* w5100设置本机ip
*参数:ip:需要设置的ip,4字节
**********************************************************************/
void drv_w5100_set_ip(uint8_t *ip)
{
uint8_t i = 0;
for (i = 0;i < 4;i++)
{
drv_w5100_tx_byte(W5100_SIPR + i,ip[i]);
}
}
/*********************************************************************
* 读取w5100的ip地址
*参数:addr:读取ip地址,4字节
**********************************************************************/
void drv_w5100_get_ip(uint8_t *ip)
{
uint8_t i = 0;
for (i = 0;i < 4;i++)
{
ip[i] = drv_w5100_rx_byte(W5100_SIPR + i);
}
}
/*********************************************************************
* w5100设置端口的端口号
*参数:socket:端口:0-3
* port:端口号
**********************************************************************/
void drv_w5100_set_socket_port(uint8_t socket,uint16_t port)
{
uint16_t reg = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_PORT + socket * 0x100;
//设置端口号
drv_w5100_tx_byte(reg,(port >> 8) & 0xff);
drv_w5100_tx_byte(reg + 1,port & 0xff);
}
/*********************************************************************
* 读取w5100端口的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t drv_w5100_get_socket_port(uint8_t socket)
{
uint16_t reg = 0;
uint16_t port = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_PORT + socket * 0x100;
//设置端口号
port = drv_w5100_rx_byte(reg);
port = (port << 8) + drv_w5100_rx_byte(reg + 1);
return port;
}
/*********************************************************************
* w5100设置端口的目的mac地址
*参数:socket:端口:0-3
* mac:需要设置的mac,6字节
**********************************************************************/
void drv_w5100_set_socket_mac(uint8_t socket,uint8_t *mac)
{
uint8_t i = 0;
uint16_t reg = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_DHAR + socket * 0x100;
//设置mac
for (i = 0;i < 6;i++)
{
drv_w5100_tx_byte(reg + i,mac[i]);
}
}
/*********************************************************************
* 读取w5100端口的目的mac地址
*参数:socket:端口:0-3
* mac:读取的目的mac,6字节
**********************************************************************/
void drv_w5100_get_socket_mac(uint8_t socket,uint8_t *mac)
{
uint8_t i = 0;
uint16_t reg = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_DHAR + socket * 0x100;
//设置mac
for (i = 0;i < 6;i++)
{
mac[i] = drv_w5100_rx_byte(reg + i);
}
}
/*********************************************************************
* w5100设置端口的目的ip地址
*参数:socket:端口:0-3
* ip:需要设置的ip,4字节
**********************************************************************/
void drv_w5100_set_socket_dst_ip(uint8_t socket,uint8_t *ip)
{
uint8_t i = 0;
uint16_t reg = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_DIPR + socket * 0x100;
//设置ip
for (i = 0;i < 4;i++)
{
drv_w5100_tx_byte(reg + i,ip[i]);
}
}
/*********************************************************************
* 读取w5100端口的目的ip地址
*参数:socket:端口:0-3
* ip:读取的目的ip,4字节
**********************************************************************/
void drv_w5100_get_socket_dst_ip(uint8_t socket,uint8_t *ip)
{
uint8_t i = 0;
uint16_t reg = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_DIPR + socket * 0x100;
//读取ip
for (i = 0;i < 4;i++)
{
ip[i] = drv_w5100_rx_byte(reg + i);
}
}
/*********************************************************************
* w5100设置端口的目的端口号
*参数:socket:端口:0-3
* port:目的端口号
**********************************************************************/
void drv_w5100_set_socket_dst_port(uint8_t socket,uint16_t port)
{
uint16_t reg = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_DPORT + socket * 0x100;
//设置端口号
drv_w5100_tx_byte(reg,(port >> 8) & 0xff);
drv_w5100_tx_byte(reg + 1,port & 0xff);
}
/*********************************************************************
* 读取w5100端口的目的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t drv_w5100_get_socket_dst_port(uint8_t socket)
{
uint16_t reg = 0;
uint16_t port = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_DPORT + socket * 0x100;
//设置端口号
port = drv_w5100_rx_byte(reg);
port = (port << 8) + drv_w5100_rx_byte(reg + 1);
return port;
}
/*********************************************************************
* 设置w5100端口缓存大小
*说明:4个端口发送总缓存为8KB,接收总缓存为8KB
*参数:tx_size:发送缓存大小数组,4字节长度,值只能取1,2,4,8这4个.单位为KB
* rx_size:发送缓存大小数组,4字节长度,值只能取1,2,4,8这4个.单位为KB
**********************************************************************/
void drv_w5100_set_socket_buf_size(uint8_t *tx_size,uint8_t *rx_size)
{
uint8_t value = 0;
uint8_t i = 0;
uint8_t tx_reg[4] = {0};
uint8_t rx_reg[4] = {0};
for (i = 0;i < 4;i++)
{
switch (tx_size[i])
{
case 1:
{
tx_reg[i] = 0;
break;
}
case 2:
{
tx_reg[i] = 1;
break;
}
case 4:
{
tx_reg[i] = 2;
break;
}
case 8:
{
tx_reg[i] = 3;
break;
}
}
switch (rx_size[i])
{
case 1:
{
rx_reg[i] = 0;
break;
}
case 2:
{
rx_reg[i] = 1;
break;
}
case 4:
{
rx_reg[i] = 2;
break;
}
case 8:
{
rx_reg[i] = 3;
break;
}
}
}
//设置写缓存大小
value = (tx_reg[3] << 6) + (tx_reg[2] << 4) + \
(tx_reg[1] << 2) + tx_reg[0];
drv_w5100_tx_byte(W5100_TMSR, value);
//设置读缓存大小
value = (rx_reg[3] << 6) + (rx_reg[2] << 4) + \
(rx_reg[1] << 2) + rx_reg[0];
drv_w5100_tx_byte(W5100_RMSR, value);
//设置缓冲区参数
for (i = 0;i < 4;i++)
{
//缓冲区大小
W5100_Tx_Buf[i].size = tx_size[i] * 1024;
W5100_Rx_Buf[i].size = rx_size[i] * 1024;
//屏蔽地址
W5100_Tx_Buf[i].mask_addr = W5100_Tx_Buf[i].size - 1;
W5100_Rx_Buf[i].mask_addr = W5100_Rx_Buf[i].size - 1;
//基地址
if (i == 0)
{
W5100_Tx_Buf[i].base_addr = W5100_TX;
W5100_Rx_Buf[i].base_addr = W5100_RX;
}
else
{
W5100_Tx_Buf[i].base_addr = W5100_Tx_Buf[i - 1].base_addr + W5100_Tx_Buf[i - 1].size;
W5100_Rx_Buf[i].base_addr = W5100_Rx_Buf[i - 1].base_addr + W5100_Tx_Buf[i - 1].size;
}
}
}
/*********************************************************************
* 读取w5100端口的发送存储器剩余空间寄存器
*参数:socket:端口:0-3
*返回:发送存储器剩余空间
**********************************************************************/
uint16_t drv_w5100_get_socket_tx_fsr(uint8_t socket)
{
uint16_t reg = 0;
uint16_t size1 = 0;
uint16_t size2 = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_TX_FSR + socket * 0x100;
while (1)
{
//读取中断寄存器
size1 = drv_w5100_rx_byte(reg);
size1 = (size1 << 8) + drv_w5100_rx_byte(reg + 1);
if (size1 != 0)
{
size2 = drv_w5100_rx_byte(reg);
size2 = (size2 << 8) + drv_w5100_rx_byte(reg + 1);
if (size1 == size2)
{
break;
}
}
}
return size1;
}
/*********************************************************************
* 读取w5100端口的接收数据字节数寄存器
*参数:socket:端口:0-3
*返回:接收数据字节数
**********************************************************************/
uint16_t drv_w5100_get_socket_rx_rsr(uint8_t socket)
{
uint16_t reg = 0;
uint16_t size1 = 0;
uint16_t size2 = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_RX_RSR + socket * 0x100;
while (1)
{
//读取中断寄存器
size1 = drv_w5100_rx_byte(reg);
size1 = (size1 << 8) + drv_w5100_rx_byte(reg + 1);
if (size1 != 0)
{
size2 = drv_w5100_rx_byte(reg);
size2 = (size2 << 8) + drv_w5100_rx_byte(reg + 1);
if (size1 == size2)
{
break;
}
}
}
return size1;
}
/*********************************************************************
* 读取w5100端口接收的数据
*参数:socket:端口:0-3
* buf:接收的数据存放的缓存
* len:读取接收数据长度
* ip:接收数据的ip
* port:接收数据的端口
**********************************************************************/
void drv_w5100_socket_rx(uint8_t socket,uint8_t *buf,uint16_t len,uint8_t *ip,uint16_t *port)
{
uint16_t shift = 0;
uint16_t addr = 0;
uint16_t reg = 0;
uint16_t size = 0;
uint16_t i = 0;
uint8_t header[8] = {0};
//读取接收缓冲区偏移量
reg = W5100_S0_RX_RR + socket * 0x100;
shift = drv_w5100_rx_byte(reg);
shift = (shift << 8) + drv_w5100_rx_byte(reg + 1);
//实际的偏移量
shift &= W5100_Rx_Buf[socket].mask_addr;
//物理地址
addr = W5100_Rx_Buf[socket].base_addr + shift;
/*
for (i = 0;i < len;i++)
{
if (shift >= W5100_Rx_Buf[socket].size)
{
addr = W5100_Rx_Buf[socket].base_addr;
shift = 0;
}
buf[i] = drv_w5100_rx_byte(addr++);
shift++;
}
*/
/*
//读取正文
if (shift + len > W5100_Rx_Buf[socket].size)
{
size = W5100_Rx_Buf[socket].size - shift;
drv_w5100_rx_buf(addr, buf, size);
drv_w5100_rx_buf(W5100_Rx_Buf[socket].base_addr, buf + size, len - size);
}
else
{
drv_w5100_rx_buf(addr, buf, len);
}
*/
//读取帧头
if (shift + 8 > W5100_Rx_Buf[socket].size)
{
size = W5100_Rx_Buf[socket].size - shift;
drv_w5100_rx_buf(addr, header, size);
drv_w5100_rx_buf(W5100_Rx_Buf[socket].base_addr, header + size, 8 - size);
shift = 8 - size;
}
else
{
drv_w5100_rx_buf(addr, header, 8);
shift += 8;
}
//保存帧头
//读取ip
ip[0] = header[0];
ip[1] = header[1];
ip[2] = header[2];
ip[3] = header[3];
//端口
*port = (header[4] << 8) + header[5];
//实际地址更改
addr = W5100_Rx_Buf[socket].base_addr + shift;
//接收数据长度更改
len -= 8;
//读取正文
if (shift + len > W5100_Rx_Buf[socket].size)
{
size = W5100_Rx_Buf[socket].size - shift;
drv_w5100_rx_buf(addr, buf, size);
drv_w5100_rx_buf(W5100_Rx_Buf[socket].base_addr, buf + size, len - size);
}
else
{
drv_w5100_rx_buf(addr, buf, len);
}
//计算下一次偏移量
shift = drv_w5100_rx_byte(reg);
shift = (shift << 8) + drv_w5100_rx_byte(reg + 1);
shift += len + 8;
drv_w5100_tx_byte(reg,(shift >> 8) & 0xff);
drv_w5100_tx_byte(reg + 1,shift & 0xff);
//接收处理完成
reg = W5100_S0_CR + socket * 0x100;
drv_w5100_tx_byte(reg,S_CR_RECV);
}
/*********************************************************************
* w5100端口发送数据
*参数:socket:端口:0-3
* buf:发送的数据存放的缓存
* len:发送数据长度
**********************************************************************/
void drv_w5100_socket_tx(uint8_t socket,uint8_t *buf,uint16_t len)
{
uint16_t shift = 0;
uint16_t addr = 0;
uint16_t reg = 0;
uint16_t size = 0;
//根据端口号选择寄存器地址
reg = W5100_S0_TX_WR + socket * 0x100;
//获得接收缓冲区读指针地址
shift = drv_w5100_rx_byte(reg);
shift = (shift << 8) + drv_w5100_rx_byte(reg + 1);
//偏移地址
shift &= W5100_Tx_Buf[socket].mask_addr;
//实际地址
addr = W5100_Tx_Buf[socket].base_addr + shift;
//发送数据
if (shift + len > W5100_Tx_Buf[socket].size)
{
size = W5100_Tx_Buf[socket].size - shift;
drv_w5100_tx_buf(addr, buf, size);
drv_w5100_tx_buf(W5100_Tx_Buf[socket].base_addr, buf + size, len - size);
}
else
{
drv_w5100_tx_buf(addr, buf, len);
}
//发送指针偏移
shift = drv_w5100_rx_byte(reg);
shift = (shift << 8) + drv_w5100_rx_byte(reg + 1);
shift += len;
drv_w5100_tx_byte(reg, (shift >> 8) & 0xff);
drv_w5100_tx_byte(reg + 1, shift & 0xff);
//根据端口号选择寄存器地址
reg = W5100_S0_CR + socket * 0x100;
//发送
drv_w5100_tx_byte(reg, S_CR_SEND);
}
inf_w5100.h
/*********************************************************************
* w5100接口层头文件
* (c)copyright 2013,jdh
* All Right Reserved
*文件名:inf_w5100.h
*程序员:jdh
*修改日期:2013/10/24
**********************************************************************/
#ifndef _INF_W5100_H_
#define _INF_W5100_H_
/*********************************************************************
* 头文件
**********************************************************************/
//驱动层头文件
#include "drv_w5100.h"
/*********************************************************************
* 数据结构
**********************************************************************/
/*********************************************************************
* 数据结构
**********************************************************************/
/*********************************************************************
* w5100端口中断信息
**********************************************************************/
struct _W5100_Socket_Irq_Msg
{
//端口中断
uint8_t socket_int;
//数据发送完成
uint8_t send_ok;
//在连接或终止,数据发送等过程超时
uint8_t timeout;
//当端口接收到数据时
uint8_t recv;
//当收到终止连接请求或终止连接过程已结束
uint8_t discon;
//当连接成功时
uint8_t con;
//接收ip
uint8_t ip[4];
//接收端口
uint16_t port;
//接收数据的字节数
uint16_t size;
};
/*********************************************************************
* w5100中断信息
**********************************************************************/
struct _W5100_Irq_Msg
{
//ip冲突
uint8_t confict;
//无法到达地址
uint8_t unreach;
//PPPoe连接关闭
uint8_t pppoe;
//端口中断信息
struct _W5100_Socket_Irq_Msg socket_msg[4];
};
/*********************************************************************
* 函数
**********************************************************************/
/*********************************************************************
* 初始化w5100
*参数:ip:本机ip,4字节
* mac:本机mac,6字节
* submask:掩码:4字节
* gateway:网关,4字节
* socket_tx_size:socket发送缓存大小,4字节
* socket_rx_size:socket接收缓存大小,4字节
**********************************************************************/
void inf_w5100_init(uint8_t *ip,uint8_t *mac,uint8_t *submask,uint8_t *gateway,\
uint8_t *socket_tx_size,uint8_t *socket_rx_size);
/*********************************************************************
* w5100设置本机ip
*参数:ip:需要设置的ip,4字节
**********************************************************************/
void inf_w5100_set_ip(uint8_t *ip);
/*********************************************************************
* 读取w5100的ip地址
*参数:addr:读取ip地址,4字节
**********************************************************************/
void inf_w5100_get_ip(uint8_t *ip);
/*********************************************************************
* w5100设置mac地址
*参数:mac:需要设置的mac,6字节
**********************************************************************/
void inf_w5100_set_mac(uint8_t *mac);
/*********************************************************************
* 读取w5100的mac地址
*参数:addr:读取mac地址,4字节
**********************************************************************/
void inf_w5100_get_mac(uint8_t *mac);
/*********************************************************************
* w5100设置网关
*参数:addr:需要设置的网关,4字节
**********************************************************************/
void inf_w5100_set_gateway(uint8_t *addr);
/*********************************************************************
* 读取w5100网关
*参数:addr:读取的网关存放地址,4字节长度
**********************************************************************/
void inf_w5100_get_gateway(uint8_t *addr);
/*********************************************************************
* w5100设置子网掩码
*参数:addr:需要设置的子网掩码,4字节
**********************************************************************/
void inf_w5100_set_submask(uint8_t *addr);
/*********************************************************************
* 读取w5100子网掩码
*参数:addr:读取的子网掩码,4字节
**********************************************************************/
void inf_w5100_get_submask(uint8_t *addr);
/*********************************************************************
* 读取w5100端口的目的ip地址
*参数:socket:端口:0-3
* ip:读取的目的ip,4字节
**********************************************************************/
void inf_w5100_get_socket_dst_ip(uint8_t socket,uint8_t *ip);
/*********************************************************************
* 读取w5100端口的目的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t inf_w5100_get_socket_dst_port(uint8_t socket);
/*********************************************************************
* 读取w5100端口的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t inf_w5100_get_socket_port(uint8_t socket);
/*********************************************************************
* w5100设置端口为udp模式
*参数:socket:端口:0-3
* port:端口号
**********************************************************************/
void inf_w5100_set_socket_udp_mode(uint8_t socket,uint16_t port);
/*********************************************************************
* w5100发送数据
*参数:socket:端口
* data:数据
* size:大小,单位字节
* ip:目标ip
* port:目标端口号
**********************************************************************/
void inf_w5100_write_data(uint16_t socket,uint8_t *data,uint16_t size,\
uint8_t *ip,uint16_t port);
/*********************************************************************
* 清除中断信息结构体
*参数:msg:中断结构体地址
**********************************************************************/
void inf_w5100_clear_w5100_irg_msg(struct _W5100_Irq_Msg *msg);
/*********************************************************************
* w5100中断处理函数
*参数:msg:中断信息
* buf0:接收socket0数据地址
* buf1:接收socket1数据地址
* buf2:接收socket2数据地址
* buf3:接收socket3数据地址
**********************************************************************/
void inf_w5100_irq_handler(struct _W5100_Irq_Msg *msg,uint8_t *buf0,uint8_t *buf1,uint8_t *buf2,uint8_t *buf3);
#endif
/*********************************************************************
* w5100接口层文件
* (c)copyright 2013,jdh
* All Right Reserved
*文件名:inf_w5100.c
*程序员:jdh
*修改日期:2013/10/24
**********************************************************************/
/*********************************************************************
* 头文件
**********************************************************************/
#include "inf_w5100.h"
/*********************************************************************
* 函数
**********************************************************************/
/*********************************************************************
* 初始化w5100
*参数:ip:本机ip,4字节
* mac:本机mac,6字节
* submask:掩码:4字节
* gateway:网关,4字节
* socket_tx_size:socket发送缓存大小,4字节
* socket_rx_size:socket接收缓存大小,4字节
**********************************************************************/
void inf_w5100_init(uint8_t *ip,uint8_t *mac,uint8_t *submask,uint8_t *gateway,\
uint8_t *socket_tx_size,uint8_t *socket_rx_size)
{
drv_w5100_init(ip,mac,submask,gateway,socket_tx_size,socket_rx_size);
}
/*********************************************************************
* w5100设置本机ip
*参数:ip:需要设置的ip,4字节
**********************************************************************/
void inf_w5100_set_ip(uint8_t *ip)
{
drv_w5100_set_ip(ip);
}
/*********************************************************************
* 读取w5100的ip地址
*参数:addr:读取ip地址,4字节
**********************************************************************/
void inf_w5100_get_ip(uint8_t *ip)
{
drv_w5100_get_ip(ip);
}
/*********************************************************************
* w5100设置mac地址
*参数:mac:需要设置的mac,6字节
**********************************************************************/
void inf_w5100_set_mac(uint8_t *mac)
{
drv_w5100_set_mac(mac);
}
/*********************************************************************
* 读取w5100的mac地址
*参数:addr:读取mac地址,4字节
**********************************************************************/
void inf_w5100_get_mac(uint8_t *mac)
{
drv_w5100_get_mac(mac);
}
/*********************************************************************
* w5100设置网关
*参数:addr:需要设置的网关,4字节
**********************************************************************/
void inf_w5100_set_gateway(uint8_t *addr)
{
drv_w5100_set_gateway(addr);
}
/*********************************************************************
* 读取w5100网关
*参数:addr:读取的网关存放地址,4字节长度
**********************************************************************/
void inf_w5100_get_gateway(uint8_t *addr)
{
drv_w5100_get_gateway(addr);
}
/*********************************************************************
* w5100设置子网掩码
*参数:addr:需要设置的子网掩码,4字节
**********************************************************************/
void inf_w5100_set_submask(uint8_t *addr)
{
drv_w5100_set_submask(addr);
}
/*********************************************************************
* 读取w5100子网掩码
*参数:addr:读取的子网掩码,4字节
**********************************************************************/
void inf_w5100_get_submask(uint8_t *addr)
{
drv_w5100_get_submask(addr);
}
/*********************************************************************
* 读取w5100端口的目的ip地址
*参数:socket:端口:0-3
* ip:读取的目的ip,4字节
**********************************************************************/
void inf_w5100_get_socket_dst_ip(uint8_t socket,uint8_t *ip)
{
drv_w5100_get_socket_dst_ip(socket,ip);
}
/*********************************************************************
* 读取w5100端口的目的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t inf_w5100_get_socket_dst_port(uint8_t socket)
{
return drv_w5100_get_socket_dst_port(socket);
}
/*********************************************************************
* 读取w5100端口的端口号
*参数:socket:端口:0-3
*返回:端口号
**********************************************************************/
uint16_t inf_w5100_get_socket_port(uint8_t socket)
{
return drv_w5100_get_socket_port(socket);
}
/*********************************************************************
* w5100设置端口为udp模式
*参数:socket:端口:0-3
* port:端口号
**********************************************************************/
void inf_w5100_set_socket_udp_mode(uint8_t socket,uint16_t port)
{
uint8_t state = 0;
uint16_t reg = 0;
while (1)
{
//设置为udp模式
//根据端口号选择寄存器地址
reg = W5100_S0_MR + socket * 0x100;
//设置端口模式
drv_w5100_tx_byte(reg,S_MR_UDP);
//设置端口号
drv_w5100_set_socket_port(socket,port);
//打开端口
//根据端口号选择寄存器地址
reg = W5100_S0_CR + socket * 0x100;
//端口开关
drv_w5100_tx_byte(reg,S_CR_OPEN);
//读取端口状态
reg = W5100_S0_SSR + socket * 0x100;
state = drv_w5100_rx_byte(reg);
if (state == S_SSR_UDP)
{
break;
}
else
{
//关闭端口
//根据端口号选择寄存器地址
reg = W5100_S0_CR + socket * 0x100;
//端口开关
drv_w5100_tx_byte(reg,0x10);
}
}
}
/*********************************************************************
* w5100发送数据
*参数:socket:端口
* data:数据
* size:大小,单位字节
* ip:目标ip,4字节
* port:目标端口号
**********************************************************************/
void inf_w5100_write_data(uint16_t socket,uint8_t *data,uint16_t size,\
uint8_t *ip,uint16_t port)
{
uint16_t free_bytes = 0;
uint8_t dst_ip[4] = {0};
//等待端口有足够空间发送
while (1)
{
free_bytes = drv_w5100_get_socket_tx_fsr(socket);
if (free_bytes >= size)
{
break;
}
}
//设置目标ip
drv_w5100_set_socket_dst_ip(socket,ip);
//设置目标端口
drv_w5100_set_socket_dst_port(socket,port);
//发送数据
drv_w5100_socket_tx(socket,data,size);
}
/*********************************************************************
* 清除中断信息结构体
*参数:msg:中断结构体地址
**********************************************************************/
void inf_w5100_clear_w5100_irg_msg(struct _W5100_Irq_Msg *msg)
{
uint8_t i = 0;
//ip冲突
msg->confict = 0;
//无法到达地址
msg->unreach = 0;
//PPPoe连接关闭
msg->pppoe = 0;
for (i = 0;i < 4;i++)
{
//端口中断
msg->socket_msg[i].socket_int = 0;
//端口中断信息
//数据发送完成
msg->socket_msg[i].send_ok = 0;
//在连接或终止,数据发送等过程超时
msg->socket_msg[i].timeout = 0;
//当端口接收到数据时
msg->socket_msg[i].recv = 0;
//当收到终止连接请求或终止连接过程已结束
msg->socket_msg[i].discon = 0;
//当连接成功时
msg->socket_msg[i].con = 0;
//ip
msg->socket_msg[i].ip[0] = 0;
msg->socket_msg[i].ip[1] = 0;
msg->socket_msg[i].ip[2] = 0;
msg->socket_msg[i].ip[3] = 0;
//端口
msg->socket_msg[i].port = 0;
//接收的字节数
msg->socket_msg[i].size = 0;
}
}
/*********************************************************************
* w5100中断处理函数
*参数:msg:中断信息
* buf0:接收socket0数据地址
* buf1:接收socket1数据地址
* buf2:接收socket2数据地址
* buf3:接收socket3数据地址
**********************************************************************/
void inf_w5100_irq_handler(struct _W5100_Irq_Msg *msg,uint8_t *buf0,uint8_t *buf1,uint8_t *buf2,uint8_t *buf3)
{
uint8_t reg_value = 0;
uint8_t i = 0;
uint8_t flag[4] = {0};
uint16_t reg_addr = 0;
uint16_t shift = 0;
//清除中断信号
inf_w5100_clear_w5100_irg_msg(msg);
//读取中断寄存器,判断中断类型
reg_value = drv_w5100_rx_byte(W5100_IR);
//清中断标志
drv_w5100_tx_byte(W5100_IR,reg_value & 0xf0);
//判断中断类型
//IP地址冲突
if ((reg_value & IR_CONFLICT) == IR_CONFLICT)
{
msg->confict = 1;
}
//无法抵达地址
if ((reg_value & IR_UNREACH) == IR_UNREACH)
{
msg->unreach = 1;
}
//端口0中断
if ((reg_value & IR_S0_INT) == IR_S0_INT)
{
flag[0] = 1;
}
//端口1中断
if ((reg_value & IR_S1_INT) == IR_S1_INT)
{
flag[1] = 1;
}
//端口2中断
if ((reg_value & IR_S2_INT) == IR_S2_INT)
{
flag[2] = 1;
}
//端口3中断
if ((reg_value & IR_S3_INT) == IR_S3_INT)
{
flag[3] = 1;
}
for (i = 0;i < 4;i++)
{
if (flag[i])
{
msg->socket_msg[i].socket_int = 1;
//读取端口中断寄存器
reg_addr = W5100_S0_IR + i * 0x100;
reg_value = drv_w5100_rx_byte(reg_addr);
//清中断标志
drv_w5100_tx_byte(reg_addr,reg_value);
//判断中断类型
//数据发送完成
if ((reg_value & S_IR_SENDOK) == S_IR_SENDOK)
{
msg->socket_msg[i].send_ok = 1;
}
//在连接或终止,数据发送等过程超时
if ((reg_value & S_IR_TIMEOUT) == S_IR_TIMEOUT)
{
msg->socket_msg[i].timeout = 1;
}
//当端口接收到数据时
if ((reg_value & S_IR_RECV) == S_IR_RECV)
{
msg->socket_msg[i].recv = 1;
msg->socket_msg[i].size = drv_w5100_get_socket_rx_rsr(i);
//读取接收字节数
switch (i)
{
case 0:
{
drv_w5100_socket_rx(i,buf0,msg->socket_msg[i].size,\
msg->socket_msg[i].ip,&msg->socket_msg[i].port);
break;
}
case 1:
{
drv_w5100_socket_rx(i,buf1,msg->socket_msg[i].size,\
msg->socket_msg[i].ip,&msg->socket_msg[i].port);
break;
}
case 2:
{
drv_w5100_socket_rx(i,buf2,msg->socket_msg[i].size,\
msg->socket_msg[i].ip,&msg->socket_msg[i].port);
break;
}
case 3:
{
drv_w5100_socket_rx(i,buf3,msg->socket_msg[i].size,\
msg->socket_msg[i].ip,&msg->socket_msg[i].port);
break;
}
}
//接收正文字节数
msg->socket_msg[i].size -= 8;
}
//当收到终止连接请求或终止连接过程已结束
if ((reg_value & S_IR_DISCON) == S_IR_DISCON)
{
msg->socket_msg[i].discon = 1;
}
//当连接成功时
if ((reg_value & S_IR_CON) == S_IR_CON)
{
msg->socket_msg[i].con = 1;
}
}
}
}
main.c:初始化w5100
int main(void)
{
uint8_t i = 0;
uint16_t buf1[3] = {1,2,3};
uint16_t buf2[10] = {0};
uint8_t ip[4] = {10,58,1,5};
uint8_t mac[6] = {0x00,0xe0,0x4c,0x36,0xc9,0xb0};
uint8_t submask[4] = {255,255,255,0};
uint8_t gateway[4] = {10,58,1,1};
uint8_t socket_tx_size[4] = {2,2,2,2};
uint8_t socket_rx_size[4] = {2,2,2,2};
uint8_t dst_ip[4] = {10,58,1,3};
uint8_t buf[3] = {'j','d','h'};
uint8_t arr[10] = {0};
//初始化设备
init_device();
#ifndef DEBUG
//打开内部看门狗
inf_enable_iwdg();
#endif
//sram测试代码
//FSMC_SRAM_WriteHalfWord(0,1);
//FSMC_SRAM_WriteHalfWord(2,2);
//FSMC_SRAM_WriteHalfWord(4,3);
//Test_Data = FSMC_SRAM_ReadHalfWord(2);
//FSMC_SRAM_WriteBuffer(buf1,0,3);
//FSMC_SRAM_ReadBuffer(buf2,0,3);
test_sram[0] = 5;
test_sram[1] = 2;
test_sram[2] = 3;
FSMC_SRAM_ReadBuffer(buf2,0,10);
__nop();
//初始化网络
inf_w5100_init(ip,mac,submask,gateway,socket_tx_size,socket_rx_size);
//打开端口
inf_w5100_set_socket_udp_mode(SOCKET0,2000);
//inf_delay_ms(5000);
//发送数据
//inf_w5100_write_data(SOCKET0,ip,4,dst_ip,2000);
//状态机执行
while (1)
{
for (i = 0;i < 6;i++)
{
inf_set_led(i + 1,LED_ON);
inf_delay_ms(10);
inf_set_led(i + 1,LED_OFF);
inf_delay_ms(10);
}
}
}
/********************************************************************* * 系统滴答中断函数 **********************************************************************/ void SysTick_Handler(void) { uint8_t ip[4] = {10,58,1,5}; uint8_t dst_ip[4] = {10,58,1,3}; char *str = "zhang ling"; Tick++; //if (Tick > 50 && Tick % 20 == 0) if (Tick > 50) { inf_w5100_write_data(SOCKET0,(uint8_t *)str,11,dst_ip,2000); } } /********************************************************************* * w5100中断处理 **********************************************************************/ void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line6) != RESET) { //清中断 EXTI_ClearITPendingBit(EXTI_Line6); //处理w5100中断 inf_w5100_irq_handler(&Msg,Buf0,Buf1,Buf2,Buf3); } }