Clion开发stm32之W5500网口库的封装

前言

  1. 本篇对网口模块W5500的库进行封装,做到对硬件层间进行解耦操作。
  2. 方便移植和网口通讯。
  3. 本篇主要是对基础功能的一个封装,后期逐步完善协议层方面的东西。
  4. 相关说明请自行参考官方文档,本篇只做驱动

W5500驱动

工具相关

头文件(net_utils.h)

#ifndef STM32_VET6_NET_UTILS_H
#define STM32_VET6_NET_UTILS_H

#include "string.h"
#include "stdint.h"
#include "stdio.h"

void convert_ip_str(uint8_t *ipAddrIn, char *ipStrOut);

int verify_ipv4_addr(char *ip);

unsigned long htonl(unsigned long hostlong);

uint16_t htons(uint16_t hostshort);

unsigned long ntohl(unsigned long netlong);

#endif //STM32_VET6_NET_UTILS_H

源文件

#include "net_utils.h"

/**
 *@brief	 	16位字符高8位低8位转换
 *@param		i:要转化的数据
 *@return	转换后的数据
 */
uint16_t swaps(uint16_t i) {
    uint16_t ret = 0;
    ret = (i & 0xFF) << 8;
    ret |= ((i >> 8) & 0xFF);
    return ret;
}

/**
 *@brief	 	32位字符高低位变换
 *@param		i:要转化的数据
 *@return	转换后的数据
 */
uint32_t swapl(uint32_t l) {
    uint32_t ret = 0;
    ret = (l & 0xFF) << 24;
    ret |= ((l >> 8) & 0xFF) << 16;
    ret |= ((l >> 16) & 0xFF) << 8;
    ret |= ((l >> 24) & 0xFF);
    return ret;
}

/**
 * @brief ip 数组转换成ip字符串
 *
 * @param ipAddr ip 数组(in)
 * @param ipStr ip 字符串(out)
 */
void convert_ip_str(uint8_t *ipAddrIn, char *ipStrOut) {
    sprintf(ipStrOut, "%d.%d.%d.%d", ipAddrIn[0], ipAddrIn[1], ipAddrIn[2], ipAddrIn[3]);
}


/**
 * @brief 验证ip 配置
 *
 * @param ip Address
 * @return u8 -1 error or 1 seccessfull
 */
int verify_ipv4_addr(char *ip) {
    if (ip == NULL || ip[0] == '0' || ip[0] == '\0') {
        return -1;
    }
    for (int i = 0, count = 0; i < strlen(ip); i++) {
        if ((ip[i] != '.') && (ip[i] < '0' || ip[i] > '9')) {
            return -1;
        }
        if (ip[i] == '.') {
            count++;
            if (count > 3) {
                return -1;
            }
        }
    }
    int ip_num[4] = {-1, -1, -1, -1};
    char ip_s[4][4];
    memset(ip_s, 0, sizeof(char[4]) * 4);
    sscanf(ip, "%[^.].%[^.].%[^.].%[^ ]", ip_s[0], ip_s[1], ip_s[2], ip_s[3]);
    sscanf(ip_s[0], "%d", &ip_num[0]);
    sscanf(ip_s[1], "%d", &ip_num[1]);
    sscanf(ip_s[2], "%d", &ip_num[2]);
    sscanf(ip_s[3], "%d", &ip_num[3]);

    for (int i = 0; i < 4; i++) {
        if (strlen(ip_s[i]) == 0 || (ip_s[i][0] == '0' && ip_s[i][1] != '\0') || ip_num[i] < 0 || ip_num[i] > 255) {
            return -1;
        }
    }

    return 0;
}

/**
 *@brief		将一个 主机模式的unsigned long型数据转换到大端模式的TCP/IP 网络字节格式的数据.
 *@param		要转换的数据
 *@return 	大端模式的数据
 */
unsigned long htonl(unsigned long hostlong) {
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)
    return swapl(hostlong);
#else
    return hostlong;
#endif
}

/**
 *@brief		将一个 主机模式的unsigned short型数据转换到大端模式的TCP/IP 网络字节格式的数据.
 *@param		要转换的数据
 *@return 	大端模式的数据
 */
uint16_t htons(uint16_t hostshort) {
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)
    return swaps(hostshort);
#else
    return hostshort;
#endif
}

/**
 *@brief		将一个大端模式的TCP/IP 网络字节格式的数据转换到主机模式的unsigned long型数据
 *@param		要转换的数据
 *@return 	unsigned long模式的数据
 */
unsigned long ntohl(unsigned long netlong) {
#if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_)
    return htonl(netlong);
#else
    return netlong;
#endif
}

寄存器相关

头文件(w5500_reg.h)

#ifndef STM32_VET6_W5500_REG_H
#define STM32_VET6_W5500_REG_H

#include "w5500_config.h"

#define MR (0x000000)
/**brief Gateway IP Register address*/
#define GAR0 (0x000100)
#define GAR1 (0x000200)
#define GAR2 (0x000300)
#define GAR3 (0x000400)
/**brief Subnet mask Register address*/
#define SUBR0 (0x000500)
#define SUBR1 (0x000600)
#define SUBR2 (0x000700)
#define SUBR3 (0x000800)
/**brief Source MAC Register address*/
#define SHAR0 (0x000900)
#define SHAR1 (0x000A00)
#define SHAR2 (0x000B00)
#define SHAR3 (0x000C00)
#define SHAR4 (0x000D00)
#define SHAR5 (0x000E00)
/**@brief Source IP Register address*/
#define SIPR0 (0x000F00)
#define SIPR1 (0x001000)
#define SIPR2 (0x001100)
#define SIPR3 (0x001200)
/**@brief set Interrupt low level timer register address*/
#define INTLEVEL0 (0x001300)
#define INTLEVEL1 (0x001400)
/**@brief Interrupt Register*/
#define IR (0x001500)
/**@brief Interrupt mask register*/
#define IMR (0x001600)
/**@brief Socket Interrupt Register*/
#define SIR (0x001700)
/**@brief Socket Interrupt Mask Register*/
#define SIMR (0x001800)
/**@brief Timeout register address( 1 is 100us )*/
#define RTR0 (0x001900)
#define RTR1 (0x001A00)
/**@brief Retry count reigster*/
#define WIZ_RCR (0x001B00)
/**@briefPPP LCP Request Timer register  in PPPoE mode*/
#define PTIMER (0x001C00)
/**@brief PPP LCP Magic number register  in PPPoE mode*/
#define PMAGIC (0x001D00)
/**@brief PPP Destination MAC Register address*/
#define PDHAR0 (0x001E00)
#define PDHAR1 (0x001F00)
#define PDHAR2 (0x002000)
#define PDHAR3 (0x002100)
#define PDHAR4 (0x002200)
#define PDHAR5 (0x002300)
/**
 @brief PPP Session Identification Register
 */
#define PSID0 (0x002400)
#define PSID1 (0x002500)
/**@brief PPP Maximum Segment Size(MSS) register*/
#define PMR0 (0x002600)
#define PMR1 (0x002700)
/**@brief Unreachable IP register address in UDP mode*/
#define UIPR0 (0x002800)
#define UIPR1 (0x002900)
#define UIPR2 (0x002A00)
#define UIPR3 (0x002B00)
/**@brief Unreachable Port register address in UDP mode*/
#define UPORT0 (0x002C00)
#define UPORT1 (0x002D00)
/**@brief PHY Configuration Register*/
#define PHYCFGR (0x002E00)
/**@brief chip version register address*/
#define VERSIONR (0x003900)
/**@brief socket Mode register*/
#define Sn_MR(ch) (0x000008 + (ch << 5))
/**@brief channel Sn_CR register*/
#define Sn_CR(ch) (0x000108 + (ch << 5))
/**@brief channel interrupt register*/
#define Sn_IR(ch) (0x000208 + (ch << 5))
/**@brief channel status register*/
#define Sn_SR(ch) (0x000308 + (ch << 5))
/**@brief source port register*/
#define Sn_PORT0(ch) (0x000408 + (ch << 5))
#define Sn_PORT1(ch) (0x000508 + (ch << 5))
/**@brief Peer MAC register address*/
#define Sn_DHAR0(ch) (0x000608 + (ch << 5))
#define Sn_DHAR1(ch) (0x000708 + (ch << 5))
#define Sn_DHAR2(ch) (0x000808 + (ch << 5))
#define Sn_DHAR3(ch) (0x000908 + (ch << 5))
#define Sn_DHAR4(ch) (0x000A08 + (ch << 5))
#define Sn_DHAR5(ch) (0x000B08 + (ch << 5))
/**@brief Peer IP register address*/
#define Sn_DIPR0(ch) (0x000C08 + (ch << 5))
#define Sn_DIPR1(ch) (0x000D08 + (ch << 5))
#define Sn_DIPR2(ch) (0x000E08 + (ch << 5))
#define Sn_DIPR3(ch) (0x000F08 + (ch << 5))
/**@brief Peer port register address*/
#define Sn_DPORT0(ch) (0x001008 + (ch << 5))
#define Sn_DPORT1(ch) (0x001108 + (ch << 5))
/**@brief Maximum Segment Size(Sn_MSSR0) register address*/
#define Sn_MSSR0(ch) (0x001208 + (ch << 5))
#define Sn_MSSR1(ch) (0x001308 + (ch << 5))

#define Sn_PROTO(ch) (0x001408 + (ch << 5))
/** @brief IP Type of Service(TOS) Register */
#define Sn_TOS(ch) (0x001508 + (ch << 5))
/**@brief IP Time to live(TTL) Register */
#define Sn_TTL(ch) (0x001608 + (ch << 5))
/**@brief Receive memory size reigster*/
#define Sn_RXMEM_SIZE(ch) (0x001E08 + (ch << 5))
/**@brief Transmit memory size reigster*/
#define Sn_TXMEM_SIZE(ch) (0x001F08 + (ch << 5))
/**@brief Transmit free memory size register*/
#define Sn_TX_FSR0(ch) (0x002008 + (ch << 5))
#define Sn_TX_FSR1(ch) (0x002108 + (ch << 5))
/**
 @brief Transmit memory read pointer register address
 */
#define Sn_TX_RD0(ch) (0x002208 + (ch << 5))
#define Sn_TX_RD1(ch) (0x002308 + (ch << 5))
/**@brief Transmit memory write pointer register address*/
#define Sn_TX_WR0(ch) (0x002408 + (ch << 5))
#define Sn_TX_WR1(ch) (0x002508 + (ch << 5))
/**@brief Received data size register*/
#define Sn_RX_RSR0(ch) (0x002608 + (ch << 5))
#define Sn_RX_RSR1(ch) (0x002708 + (ch << 5))
/**@brief Read point of Receive memory*/
#define Sn_RX_RD0(ch) (0x002808 + (ch << 5))
#define Sn_RX_RD1(ch) (0x002908 + (ch << 5))
/**@brief Write point of Receive memory*/
#define Sn_RX_WR0(ch) (0x002A08 + (ch << 5))
#define Sn_RX_WR1(ch) (0x002B08 + (ch << 5))
/**@brief socket interrupt mask register*/
#define Sn_IMR(ch) (0x002C08 + (ch << 5))
/**@brief frag field value in IP header register*/
#define Sn_FRAG(ch) (0x002D08 + (ch << 5))
/**@brief Keep Timer register*/
#define Sn_KPALVTR(ch) (0x002F08 + (ch << 5))

/* MODE register values */
#define MR_RST 0x80      /**< reset */
#define MR_WOL 0x20      /**< Wake on Lan */
#define MR_PB 0x10       /**< ping block */
#define MR_PPPOE 0x08    /**< enable pppoe */
#define MR_UDP_FARP 0x02 /**< enbale FORCE ARP */
/* IR register values */
#define IR_CONFLICT 0x80 /**< check ip confict */
#define IR_UNREACH 0x40  /**< get the destination unreachable message in UDP sending */
#define IR_PPPoE 0x20    /**< get the PPPoE close message */
#define IR_MAGIC 0x10    /**< get the magic packet interrupt */

/* Sn_MR values */
#define Sn_MR_CLOSE 0x00  /**< unused socket */
#define Sn_MR_TCP 0x01    /**< TCP */
#define Sn_MR_UDP 0x02    /**< UDP */
#define Sn_MR_IPRAW 0x03  /**< IP LAYER RAW SOCK */
#define Sn_MR_MACRAW 0x04 /**< MAC LAYER RAW SOCK */
#define Sn_MR_PPPOE 0x05  /**< PPPoE */
#define Sn_MR_UCASTB 0x10 /**< Unicast Block in UDP Multicating*/
#define Sn_MR_ND 0x20     /**< No Delayed Ack(TCP) flag */
#define Sn_MR_MC 0x20     /**< Multicast IGMP (UDP) flag */
#define Sn_MR_BCASTB 0x40 /**< Broadcast blcok in UDP Multicating */
#define Sn_MR_MULTI 0x80  /**< support UDP Multicating */

/* Sn_MR values on MACRAW MODE */
#define Sn_MR_MIP6N 0x10 /**< IPv6 packet Block */
#define Sn_MR_MMB 0x20   /**< IPv4 Multicasting Block */
//#define Sn_MR_BCASTB                 0x40     /**< Broadcast blcok */
#define Sn_MR_MFEN 0x80 /**< support MAC filter enable */

/* Sn_CR values */
#define Sn_CR_OPEN 0x01      /**< initialize or open socket */
#define Sn_CR_LISTEN 0x02    /**< wait connection request in tcp mode(Server mode) */
#define Sn_CR_CONNECT 0x04   /**< send connection request in tcp mode(Client mode) */
#define Sn_CR_DISCON 0x08    /**< send closing reqeuset in tcp mode */
#define Sn_CR_CLOSE 0x10     /**< close socket */
#define Sn_CR_SEND 0x20      /**< update txbuf pointer, send data */
#define Sn_CR_SEND_MAC 0x21  /**< send data with MAC address, so without ARP process */
#define Sn_CR_SEND_KEEP 0x22 /**<  send keep alive message */
#define Sn_CR_RECV 0x40      /**< update rxbuf pointer, recv data */

#ifdef __DEF_IINCHIP_PPP__
#define Sn_CR_PCON 0x23
#define Sn_CR_PDISCON 0x24
#define Sn_CR_PCR 0x25
#define Sn_CR_PCN 0x26
#define Sn_CR_PCJ 0x27
#endif

/* Sn_IR values */
#ifdef __DEF_IINCHIP_PPP__
#define Sn_IR_PRECV 0x80
#define Sn_IR_PFAIL 0x40
#define Sn_IR_PNEXT 0x20
#endif

#define Sn_IR_SEND_OK 0x10 /**< complete sending */
#define Sn_IR_TIMEOUT 0x08 /**< assert timeout */
#define Sn_IR_RECV 0x04    /**< receiving data */
#define Sn_IR_DISCON 0x02  /**< closed socket */
#define Sn_IR_CON 0x01     /**< established connection */

/* Sn_SR values */
#define SOCK_CLOSED 0x00      /**< closed */
#define SOCK_INIT 0x13        /**< init state */
#define SOCK_LISTEN 0x14      /**< listen state */
#define SOCK_SYNSENT 0x15     /**< connection state */
#define SOCK_SYNRECV 0x16     /**< connection state */
#define SOCK_ESTABLISHED 0x17 /**< success to connect */
#define SOCK_FIN_WAIT 0x18    /**< closing state */
#define SOCK_CLOSING 0x1A     /**< closing state */
#define SOCK_TIME_WAIT 0x1B   /**< closing state */
#define SOCK_CLOSE_WAIT 0x1C  /**< closing state */
#define SOCK_LAST_ACK 0x1D    /**< closing state */
#define SOCK_UDP 0x22         /**< udp socket */
#define SOCK_IPRAW 0x32       /**< ip raw mode socket */
#define SOCK_MACRAW 0x42      /**< mac raw mode socket */
#define SOCK_PPPOE 0x5F       /**< pppoe socket */

/* IP PROTOCOL */
#define IPPROTO_IP 0    /**< Dummy for IP */
#define IPPROTO_ICMP 1  /**< Control message protocol */
#define IPPROTO_IGMP 2  /**< Internet group management protocol */
#define IPPROTO_GGP 3   /**< Gateway^2 (deprecated) */
#define IPPROTO_TCP 6   /**< TCP */
#define IPPROTO_PUP 12  /**< PUP */
#define IPPROTO_UDP 17  /**< UDP */
#define IPPROTO_IDP 22  /**< XNS idp */
#define IPPROTO_ND 77   /**< UNOFFICIAL net disk protocol */
#define IPPROTO_RAW 255 /**< Raw IP packet */

/*********************************************************
 * iinchip access function
 *********************************************************/



void Chip_Init(void);                              // reset iinchip

void setMR(uint8_t val);

void getMR(void);

void Set_RTR(uint16_t timeout); // set retry duration for data transmission, connection, closing ...
void Set_RCR(uint8_t retry);    // set retry count (above the value, assert timeout interrupt)
void Clear_IR(uint8_t mask);    // clear interrupt
uint8_t Read_IR(void);

void setSn_MSS(uint8_t s, uint16_t Sn_MSSR); // set maximum segment size
uint8_t getSn_IR(uint8_t s);                 // get socket interrupt status
uint8_t getSn_SR(uint8_t s);                 // get socket status
uint16_t getSn_TX_FSR(uint8_t s);            // get socket TX free buf size
uint16_t getSn_RX_RSR(uint8_t s);            // get socket RX recv buf size
uint8_t getSn_SR(uint8_t s);

uint8_t getRCR(void);

void setRCR(uint8_t retry);

void setSn_TTL(uint8_t s, uint8_t ttl);

void send_data_processing(uint8_t s, uint8_t *wizdata, uint16_t len);

void recv_data_processing(uint8_t s, uint8_t *wizdata, uint16_t len);

void setSn_IR(uint8_t s, uint8_t val);

void setGAR(uint8_t *addr);  // set gateway address
void setSUBR(uint8_t *addr); // set subnet mask address
void setSHAR(uint8_t *addr); // set local MAC address
void setSIPR(uint8_t *addr); // set local IP address
void getGAR(uint8_t *addr);

void getSUBR(uint8_t *addr);

void getSHAR(uint8_t *addr);

void getSIPR(uint8_t *addr);

#endif //STM32_VET6_W5500_REG_H

源文件

#include "w5500_reg.h"

/**
 *@brief		This function is to get the Max size to receive.
 *@param		s: socket number
 *@return	This function return the RX buffer size has been setted
 */
void Chip_Init(void) {
    setMR(MR_RST);
}

/**
 *@brief		This function is to set up gateway IP address.
 *@param		addr: a pointer to a 4 -byte array responsible to set the Gateway IP address
 *@return	None
 */
void setGAR(uint8_t *addr) {
    W5500_Write_Buf(GAR0, addr, 4);
}

uint8_t getRCR(void) {
    return W5500_Read(WIZ_RCR);
}

/**
@brief  This function set the number of Retransmission.

If there is no response from the peer or delay in response then recorded time
as per RTR & RCR register seeting then time out will occur.
*/
void setRCR(uint8_t retry) {
    W5500_Write(WIZ_RCR, retry);
}

/**
 *@brief		This function is to get gateway IP address.
 *@param		addr: a pointer to a 4 -byte array responsible to get the Gateway IP address
 *@return	None
 */
void getGAR(uint8_t *addr) {
    W5500_Read_Buf(GAR0, addr, 4);
}

/**
 *@brief 	This function is to set up SubnetMask address
 *@param		addr: a pointer to a 4 -byte array responsible to set the subway IP address.
 *@return	None
 */
void setSUBR(uint8_t *addr) {
    W5500_Write_Buf(SUBR0, addr, 4);
}

/**
 *@brief		This function is to set up MAC address.
 *@param		addr: a pointer to a 6 -byte array responsible to set the MAC address.
 *@return	None
 */
void setSHAR(uint8_t *addr) {
    W5500_Write_Buf(SHAR0, addr, 6);
}

/**
 *@brief		This function is to set up Source IP address.
 *@param		addr:a pointer to a 4 -byte array responsible to set the Source IP addres.
 *@return	None
 */
void setSIPR(uint8_t *addr) {
    W5500_Write_Buf(SIPR0, addr, 4);
}

/**
 *@brief		This function is to get Subnet mask.
 *@param		addr:a pointer to a 4 -byte array responsible to set the Subnet mask.
 *@return	None
 */
void getSUBR(uint8_t *addr) {
    W5500_Read_Buf(SUBR0, addr, 4);
}

/**
 *@brief		This function is to get up Source MAC .
 *@param		addr: a pointer to a 6 -byte array responsible to get the MAC
 *@return	None
 */
void getSHAR(uint8_t *addr) {
    W5500_Read_Buf(SHAR0, addr, 6);
}

/**
 *@brief		This function is to get up Source IP .
 *@param		addr: a pointer to a 4 -byte array responsible to get the Source IP
 *@return	None
 */
void getSIPR(uint8_t *addr) {
    W5500_Read_Buf(SIPR0, addr, 4);
}

/**
 *@brief		This function is to set the MR register.
 *@param		val: the value to set to MR
 *@return	None
 */
void setMR(uint8_t val) {
    W5500_Write(MR, val);
}

void getMR(void) {
    W5500_Read(MR);
}

/**
 *@brief		This function is to get Interrupt register in common register.
 *@param		None
 *@return	The value read from the IR register
 */
uint8_t Read_IR(void) {
    return W5500_Read(IR);
}

/**
@brief		This function is to set up Retransmission time.
          If there is no response from the peer or delay in response then retransmission
          will be there as per RTR (Retry Time-value Register)setting
*@param		timeout: The value write to  the RTR0 register
*@return	None
*/
void Set_RTR(uint16_t timeout) {
    W5500_Write(RTR0, (uint8_t) ((timeout & 0xff00) >> 8));
    W5500_Write(RTR1, (uint8_t) (timeout & 0x00ff));
}

/**
@brief		This function is to set the number of Retransmission.
          If there is no response from the peer or delay in response then recorded time
          as per RTR & RCR register seeting then time out will occur.
*@param		retry: Times to  retry
*@return	None
*/
void Set_RCR(uint8_t retry) {
    W5500_Write(WIZ_RCR, retry);
}

/**
*@brief		This function is to the interrupt mask Enable/Disable appropriate Interrupt. ('1' : interrupt enable)
          If any bit in IMR is set as '0' then there is not interrupt signal though the bit is
          set in IR register.
*@param		mask: the bits to clear
*@return	None
*/
void Clear_IR(uint8_t mask) {
    W5500_Write(IR, ~mask | Read_IR());
}

/**
 *@brief  	This function is to set the maximum segment size of TCP in Active Mode), while in Passive Mode this is set by peer
 *@param		s: socket number
 *@param		Sn_MSSR: the maximum segment size
 *@return	None
 */
void setSn_MSS(uint8_t s, uint16_t Sn_MSSR) {
    W5500_Write(Sn_MSSR0(s), (uint8_t) ((Sn_MSSR & 0xff00) >> 8));
    W5500_Write(Sn_MSSR1(s), (uint8_t) (Sn_MSSR & 0x00ff));
}

/**
 *@brief  	This function is to set the IP Time to live(TTL) Register
 *@param		s: socket number
 *@param		Sn_MSSR: the IP Time to live
 *@return	None
 */
void setSn_TTL(uint8_t s, uint8_t ttl) {
    W5500_Write(Sn_TTL(s), ttl);
}

/**
 *@brief		This function is to read the Interrupt & Soket Status registe
 *@param		s: socket number
 *@return	socket interrupt status
 */
uint8_t getSn_IR(uint8_t s) {
    return W5500_Read(Sn_IR(s));
}

/**
 *@brief 	This function is to write the Interrupt & Soket Status register to clear the interrupt
 *@param		s: socket number
 *@return  socket interrupt status
 */
void setSn_IR(uint8_t s, uint8_t val) {
    W5500_Write(Sn_IR(s), val);
}

/**
 *@brief 	This function is to get socket status
 *@param		s: socket number
 *@return  socket status
 */
uint8_t getSn_SR(uint8_t s) {
    return W5500_Read(Sn_SR(s));
}

/**
*@brief		This fuction is to get socket TX free buf size
          This gives free buffer size of transmit buffer. This is the data size that user can transmit.
          User shuold check this value first and control the size of transmitting data
*@param		s: socket number
*@return  socket TX free buf size
*/
uint16_t getSn_TX_FSR(uint8_t s) {
    uint16_t val = 0, val1 = 0;
    do {
        val1 = W5500_Read(Sn_TX_FSR0(s));
        val1 = (val1 << 8) + W5500_Read(Sn_TX_FSR1(s));
        if (val1 != 0) {
            val = W5500_Read(Sn_TX_FSR0(s));
            val = (val << 8) + W5500_Read(Sn_TX_FSR1(s));
        }
    } while (val != val1);
    return val;
}

/**
 *@brief		This fuction is to give size of received data in receive buffer.
 *@param		s: socket number
 *@return  socket TX free buf size
 */
uint16_t getSn_RX_RSR(uint8_t s) {
    uint16_t val = 0, val1 = 0;
    do {
        val1 = W5500_Read(Sn_RX_RSR0(s));
        val1 = (val1 << 8) + W5500_Read(Sn_RX_RSR1(s));
        if (val1 != 0) {
            val = W5500_Read(Sn_RX_RSR0(s));
            val = (val << 8) + W5500_Read(Sn_RX_RSR1(s));
        }
    } while (val != val1);
    return val;
}

/**
*@brief   This function is being called by send() and sendto() function also.

          This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
          register. User should read upper byte first and lower byte later to get proper value.
*@param		s: socket number
*@param		data: data buffer to send
*@param		len: data length
*@return  socket TX free buf size
*/
void send_data_processing(uint8_t s, uint8_t *data, uint16_t len) {
    uint16_t ptr = 0;
    uint32_t addrbsb = 0;
    if (len == 0) {
        w5500_ps("CH: %d Unexpected1 length 0\r\n", s);
        return;
    }

    ptr = W5500_Read(Sn_TX_WR0(s));
    ptr = ((ptr & 0x00ff) << 8) + W5500_Read(Sn_TX_WR1(s));

    addrbsb = (uint32_t)(ptr << 8) + (s << 5) + 0x10;
    W5500_Write_Buf(addrbsb, data, len);

    ptr += len;
    W5500_Write(Sn_TX_WR0(s), (uint8_t) ((ptr & 0xff00) >> 8));
    W5500_Write(Sn_TX_WR1(s), (uint8_t) (ptr & 0x00ff));
}

/**
*@brief  	This function is being called by recv() also.
          This function read the Rx read pointer register
          and after copy the data from receive buffer update the Rx write pointer register.
          User should read upper byte first and lower byte later to get proper value.
*@param		s: socket number
*@param		data: data buffer to receive
*@param		len: data length
*@return  None
*/
void recv_data_processing(uint8_t s, uint8_t *data, uint16_t len) {
    uint16_t ptr = 0;
    uint32_t addrbsb = 0;

    if (len == 0) {
        w5500_ps("CH: %d Unexpected2 length 0\r\n", s);
        return;
    }

    ptr = W5500_Read(Sn_RX_RD0(s));
    ptr = ((ptr & 0x00ff) << 8) + W5500_Read(Sn_RX_RD1(s));

    addrbsb = (uint32_t)(ptr << 8) + (s << 5) + 0x18;
    W5500_Read_Buf(addrbsb, data, len);
    ptr += len;

    W5500_Write(Sn_RX_RD0(s), (uint8_t) ((ptr & 0xff00) >> 8));
    W5500_Write(Sn_RX_RD1(s), (uint8_t) (ptr & 0x00ff));
}


配置相关

头文件(w5500_config.h)

#ifndef STM32_VET6_W5500_CONFIG_H
#define STM32_VET6_W5500_CONFIG_H

#include "sys.h"
#include "socket.h"
#include "net_utils.h"
#include "w5500_port.h"
#include "w5500_reg.h"

#if NET_DEBUG_LOG == 1
#define w5500_ps(fmt, ...) os_ps(fmt,##__VA_ARGS__)
#else
#define w5500_ps(fmt, ...)
#endif
#define MAX_SOCK_NUM 4
typedef struct __attribute__((packed)) {
    uint8_t ip_addr[4];
    uint8_t gw[4];
    uint8_t sub[4];
    uint8_t dns[4];
    uint8_t mac[6];
    uint16_t port;
} Net_Config_t;
/**
 * @brief 网络配置结构体字节数
 */
#define NET_CONFIG_SIZE sizeof(Net_Config_t)
extern Net_Config_t Default_Net_Config;

/***********************************************************************函数定义***********************************************************/
void Net_Reset(void);

uint8_t *Net_Mac_Get(void);

void Net_Config_Init(void);

void Net_Set_Mac(void);

void Net_Conf_Buf_Init(void);

void Net_Config_Set(Net_Config_t *net_conf);

bool check_net_cnf(Net_Config_t *dst);

void Net_Info_Print(Net_Config_t *net_conf);

uint8_t W5500_Read(uint32_t addrbsb);

void W5500_Write(uint32_t addrbsb, uint8_t data);

uint16_t W5500_Write_Buf(uint32_t addrbsb, uint8_t *buf, uint16_t len);

uint16_t W5500_Read_Buf(uint32_t addrbsb, uint8_t *buf, uint16_t len);

#endif //STM32_VET6_W5500_CONFIG_H

源文件

#include "w5500_config.h"


uint16_t SSIZE[8] = {0};                      // Max Tx buffer
uint16_t RSIZE[8] = {0};                      // Max Rx buffer
uint8_t txsize[8] = {4, 4, 4, 4, 0, 0, 0, 0}; // tx buffer set	K bits
uint8_t rxsize[8] = {4, 4, 4, 4, 0, 0, 0, 0}; // rx buffet set  K bits
Net_Config_t Default_Net_Config = {
        .gw = {192, 168, 8, 1},
        .sub = {255, 255, 255, 0},
        .dns = {114, 114, 114, 114},
        .ip_addr = {192, 168, 8, 54},
        .port = 1225,
};

/**
 * @brief 存储mac地址
 */
uint8_t net_service_mac[6] = {0x00};

/**
 *@brief		写入一个8位数据到W5500
 *@param		addrbsb: 写入数据的地址
 *@param   		data:写入的8位数据
 *@return	无
 */
void W5500_Write(uint32_t addrbsb, uint8_t data) {
    W5500_CS_LOW();
    W5500_SPI_WritByte((addrbsb & 0x00FF0000) >> 16);
    W5500_SPI_WritByte((addrbsb & 0x0000FF00) >> 8);
    W5500_SPI_WritByte((addrbsb & 0x000000F8) + 4);
    W5500_SPI_WritByte(data);
    W5500_CS_HIGH();
}

/**
 *@brief		从W5500读出一个8位数据
 *@param		addrbsb: 写入数据的地址
 *@param   data:从写入的地址处读取到的8位数据
 *@return	无
 */
uint8_t W5500_Read(uint32_t addrbsb) {
    uint8_t data = 0;
    W5500_CS_LOW();
    W5500_SPI_WritByte((addrbsb & 0x00FF0000) >> 16);
    W5500_SPI_WritByte((addrbsb & 0x0000FF00) >> 8);
    W5500_SPI_WritByte((addrbsb & 0x000000F8));
    data = W5500_SPI_WritByte(0x00);
    W5500_CS_HIGH();
    return data;
}

/**
 *@brief		向W5500写入len字节数据
 *@param		addrbsb: 写入数据的地址
 *@param   buf:写入字符串
 *@param   len:字符串长度
 *@return	len:返回字符串长度
 */
uint16_t W5500_Write_Buf(uint32_t addrbsb, uint8_t *buf, uint16_t len) {
    uint16_t idx = 0;
    if (len == 0) {
        w5500_ps("Unexpected2 length 0\r\n");
    }
    W5500_CS_LOW();
    W5500_SPI_WritByte((addrbsb & 0x00FF0000) >> 16);
    W5500_SPI_WritByte((addrbsb & 0x0000FF00) >> 8);
    W5500_SPI_WritByte((addrbsb & 0x000000F8) + 4);
    for (idx = 0; idx < len; idx++) {
        W5500_SPI_WritByte(buf[idx]);
    }
    W5500_CS_HIGH();
    return len;
}

/**
 *@brief		从W5500读出len字节数据
 *@param		addrbsb: 读取数据的地址
 *@param 		buf:存放读取数据
 *@param		len:字符串长度
 *@return		len:返回字符串长度
 */
uint16_t W5500_Read_Buf(uint32_t addrbsb, uint8_t *buf, uint16_t len) {
    uint16_t idx = 0;
    if (len == 0) {
        w5500_ps("Unexpected2 length 0\r\n");
    }
    W5500_CS_LOW();
    W5500_SPI_WritByte((addrbsb & 0x00FF0000) >> 16);
    W5500_SPI_WritByte((addrbsb & 0x0000FF00) >> 8);
    W5500_SPI_WritByte((addrbsb & 0x000000F8));
    for (idx = 0; idx < len; idx++) {
        buf[idx] = W5500_SPI_WritByte(0x00);
    }
    W5500_CS_HIGH();
    return len;
}

/**
 * @brief 重置网口芯片
 */
void Net_Reset(void) {
    W5500_RST_LOW();
    HAL_Delay(1);
    W5500_RST_HIGH();
    HAL_Delay(1600);
}

/**
 * @brief 获取mac地址
 * @return 返回mac地址
 */
uint8_t *Net_Mac_Get(void) {
    uint32_t uid0 = HAL_GetUIDw0();
    uint32_t uid1 = HAL_GetUIDw1();
    uint32_t uid2 = HAL_GetUIDw2();
    uint8_t mac[6] = {0, uid0 >> 8, uid1, uid1 >> 8, uid2, uid2 >> 8};
    memcpy(net_service_mac, mac, sizeof(mac));
    return net_service_mac;
}

void socket_buf_set(uint8_t s, uint8_t tx_size, uint8_t rx_size) {
    W5500_Write((Sn_TXMEM_SIZE(s)), tx_size);
    W5500_Write((Sn_RXMEM_SIZE(s)), rx_size);
    SSIZE[s] = (uint16_t) tx_size * (1024);
    RSIZE[s] = (uint16_t) rx_size * (1024);
}

void socket_buf_init(uint8_t *tx_size, uint8_t *rx_size) {
    ;
    for (uint8_t i = 0;
         i < MAX_SOCK_NUM; i++) // Set the size, masking and base address of Tx & Rx memory by each channel
    {
        socket_buf_set(i, tx_size[i], rx_size[i]);
        setSn_TTL(i, TTL_SEC);
    }
}

void Net_Config_Init(void) {
    Net_Reset();
}

void Net_Set_Mac(void) {
    // 设置mac地址
    setSHAR(Net_Mac_Get());
    memcpy(Default_Net_Config.mac, net_service_mac, sizeof(net_service_mac));
}

void Net_Conf_Buf_Init(void) {
    socket_buf_init(txsize, rxsize);
}

/**
 * @brief 网络配置
 * @param net_conf 配置结构体指针
 */
void Net_Config_Set(Net_Config_t *net_conf) {
    Net_Set_Mac();
    setSUBR(net_conf->sub);
    setGAR(net_conf->gw);
    setSIPR(net_conf->ip_addr);
    uint8_t buf[4];
    getSIPR(buf);
    w5500_ps("ip addr:%d-%d-%d-%d\r\n", buf[0], buf[1], buf[2], buf[3]);
    // 配置socket缓存大小
    //	socket_buf_init(txsize, rxsize);
    Net_Conf_Buf_Init();
}

bool check_net_cnf(Net_Config_t *dst) {
    return (cmp_equal(dst->ip_addr, dst->gw, 3) && cmp_equal(Default_Net_Config.sub, dst->sub, 3))
           && (!cmp_equal(dst->ip_addr, dst->gw, 4))
           && !cmp_equal(dst->ip_addr, Default_Net_Config.sub, 3);
}

void Net_Info_Print(Net_Config_t *net_conf) {
#if NET_DEBUG_LOG == 1
    w5500_ps("ip:%d.%d.%d.%d\r\n", net_conf->ip_addr[0], net_conf->ip_addr[1], net_conf->ip_addr[2],
             net_conf->ip_addr[3]);
    w5500_ps("gw:%d.%d.%d.%d\r\n", net_conf->gw[0], net_conf->gw[1], net_conf->gw[2], net_conf->gw[3]);
    w5500_ps("sub:%d.%d.%d.%d\r\n", net_conf->sub[0], net_conf->sub[1], net_conf->sub[2], net_conf->sub[3]);
#endif

}

/**
 * @brief 检测物理层连接
 * @return
 */
void W5500_Phy_Check(void) {
    uint8_t phyConnect = 0x01 & W5500_Read(PHYCFGR);
    if (phyConnect == 0) {
        phyConnect = 0;
        do {
            close(phyConnect++);
        } while (phyConnect < 4);
        phyConnect = 0;
        while (phyConnect == 0) {
            phyConnect = 0x01 & W5500_Read(PHYCFGR);
            HAL_Delay(500);
            w5500_ps("please check net driver connect\r\n");
        }
    }
}

bool W5500_Check_Hard(void) {
    return (0x01 & W5500_Read(PHYCFGR)) != 0;
}

调用层相关

头文件

#ifndef STM32_VET6_SOCKET_H
#define STM32_VET6_SOCKET_H

#include "w5500_config.h"


#define TTL_SEC 2
typedef uint8_t SOCKET;
#define TCP_CLIENT_LISTEN_PORT 3000
#define UDP_CLIENT_LISTEN_PORT 4000

typedef struct {
    uint8_t ip[4];
    uint16_t port;
} Net_Conn_t; //
typedef struct {
    uint8_t *buf;
    uint16_t buf_len;
} Net_Data_t;

// Opens a socket(TCP or UDP or IP_RAW mode)
extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag);

// Close socket
extern void close(SOCKET s);

// Establish TCP connection (Active connection)
extern uint8_t connect(SOCKET s, uint8_t *addr, uint16_t port);

extern void disconnect(SOCKET s);                                                       // disconnect the connection
extern uint8_t
listen(SOCKET s);                                                          // Establish TCP connection (Passive connection)
extern uint16_t send(SOCKET s, const uint8_t *buf, uint16_t len);                             // Send data (TCP)
extern uint16_t recv(SOCKET s, uint8_t *buf, uint16_t len);                                   // Receive data (TCP)
// Send data (UDP/IP RAW)
extern uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port);

// Receive data (UDP/IP RAW)
extern uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port);

extern uint8_t getSocketStatus(SOCKET s);

extern void clearSocketFlag(SOCKET s);

extern uint16_t getSocketRecDataLen(SOCKET s);


bool do_tcp_connect(SOCKET s, uint8_t *remote_ip, uint16_t remote_port);

bool do_tcp_send(SOCKET s, Net_Data_t *net_data);

bool do_tcp_send_buf(SOCKET s, uint8_t *buf, uint16_t buf_len);

bool do_tcp_send_str(SOCKET s, char *str);

bool do_tcp_receive(SOCKET s, Net_Data_t *net_data);

bool do_udp_listen(SOCKET s, uint16_t listen_port, Net_Conn_t *net_conn, Net_Data_t *net_data);

bool do_udp_send(SOCKET s, Net_Conn_t *net_conn, Net_Data_t *net_data);


/******************************************新版API********************************************/

uint8_t udp_socket_status(SOCKET s);

bool udp_socket_init(SOCKET s, uint16_t local_port);

bool udp_send(SOCKET s, uint8_t *dst_ip, uint16_t dst_port, uint8_t *data, uint16_t len);

bool udp_rec(SOCKET s, uint16_t listen_port, uint8_t *dstIp, uint16_t *dstPort, uint8_t *recData, uint16_t *recLen);

uint8_t tcp_client_status(SOCKET s);

void tcp_client_connect(SOCKET s, uint8_t *dst_ip, uint16_t dst_port);

bool tcp_client_send(SOCKET s, uint8_t *data, uint16_t len);

void tcp_server_init(SOCKET s, uint16_t listen_port, Net_Data_t *netData);

Net_Data_t *tcp_server_listen(SOCKET s);

void tcp_server_resp(SOCKET s, uint8_t *data, uint16_t len);

bool tcp_listen(SOCKET s, uint16_t listen_port, Net_Data_t *net_data);

#endif //STM32_VET6_SOCKET_H

源文件

#include "socket.h"


uint16_t socket_port[MAX_SOCK_NUM];
uint16_t udp_local_port = 8080;
Net_Data_t *socket_net_data[MAX_SOCK_NUM];
extern uint16_t SSIZE[8]; // Max Tx buffer
/****************************************************************
 * @Date: 2022-08-27 13:44:17
 * @Funticon name: 已接收数据的长度
 * @Berif:
 * @Author: scl
 * @Note:
 * @param {SOCKET} s
 * @return {*}
 ******************************************************************/
uint16_t getSocketRecDataLen(SOCKET s) {
    return getSn_RX_RSR(s);
}

/****************************************************************
 * @Date: 2022-08-27 13:39:17
 * @Funticon name: 清除socket 中断标志位
 * @Berif:
 * @Author: scl
 * @Note:
 * @param {SOCKET} s
 * @return {*}
 ******************************************************************/
void clearSocketFlag(SOCKET s) {
    uint8_t stat = getSn_IR(s);
    if (stat & Sn_IR_CON) // tcp
    {
        setSn_IR(s, Sn_IR_CON); /*清除接收中断标志位*/
        return;
    }
    if (stat & Sn_IR_RECV) {
        setSn_IR(s, Sn_IR_RECV); /*清接收中断*/
        return;
    }
}

/****************************************************************
 * @Date: 2022-08-27 13:37:46
 * @Funticon name: 获取socket 状态
 * @Berif:
 * @Author: scl
 * @Note:
 * @param {SOCKET} s
 * @return {*}
 ******************************************************************/
uint8_t getSocketStatus(SOCKET s) {
    return getSn_SR(s);
}

/**
*@brief   This Socket function initialize the channel in perticular mode,
			   and set the port and wait for W5200 done it.
*@param		s: socket number.
*@param		protocol: The socket to chose.
*@param		port:The port to bind.
*@param		flag: Set some bit of MR,such as **< No Delayed Ack(TCP) flag.
*@return  1 for sucess else 0.
*/
uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) {
    uint8_t ret;
    if (((protocol & 0x0F) == Sn_MR_TCP) || ((protocol & 0x0F) == Sn_MR_UDP) ||
        ((protocol & 0x0F) == Sn_MR_IPRAW) ||
        ((protocol & 0x0F) == Sn_MR_MACRAW) ||
        ((protocol & 0x0F) == Sn_MR_PPPOE)) {
        close(s);
        W5500_Write(Sn_MR(s), protocol | flag);
        if (port != 0) {
            W5500_Write(Sn_PORT0(s), (uint8_t) ((port & 0xff00) >> 8));
            W5500_Write(Sn_PORT1(s), (uint8_t) (port & 0x00ff));
        } else {
            // local_port++; // if don't set the source port, set local_port number.
            // W5500_Write(Sn_PORT0(s), (uint8_t)((local_port & 0xff00) >> 8));
            // W5500_Write(Sn_PORT1(s), (uint8_t)(local_port & 0x00ff));
            return 0;
        }
        W5500_Write(Sn_CR(s), Sn_CR_OPEN); // run sockinit Sn_CR

        /* wait to process the command... */
        while (W5500_Read(Sn_CR(s)));
        /* ------- */
        ret = 1;
    } else {
        ret = 0;
    }
    return ret;
}

/**
 *@brief   This function close the socket and parameter is "s" which represent
 *the socket number
 *@param		s: socket number.
 *@return  None
 */
void close(SOCKET s) {

    W5500_Write(Sn_CR(s), Sn_CR_CLOSE);

    /* wait to process the command... */
    while (W5500_Read(Sn_CR(s))); /* ------- */

    W5500_Write(Sn_IR(s), 0xFF); /* all clear */
}

/**
*@brief   This function established  the connection for the channel in passive
(server) mode. This function waits for the request from the peer.
*@param		s: socket number.
*@return  1 for success else 0.
*/
uint8_t listen(SOCKET s) {
    uint8_t ret;
    if (W5500_Read(Sn_SR(s)) == SOCK_INIT) {
        W5500_Write(Sn_CR(s), Sn_CR_LISTEN);
        /* wait to process the command... */
        while (W5500_Read(Sn_CR(s)));
        /* ------- */
        ret = 1;
    } else {
        ret = 0;
    }
    return ret;
}

/**
*@brief		This function established  the connection for the channel in
Active (client) mode. This function waits for the untill the connection is
established.
*@param		s: socket number.
*@param		addr: The server IP address to connect
*@param		port: The server IP port to connect
*@return  1 for success else 0.
*/
uint8_t connect(SOCKET s, uint8_t *addr, uint16_t port) {
    uint8_t ret;
    if (((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) &&
         (addr[3] == 0xFF)) ||
        ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) &&
         (addr[3] == 0x00)) ||
        (port == 0x00)) {
        ret = 0;
    } else {
        ret = 1;
        // set destination IP
        W5500_Write(Sn_DIPR0(s), addr[0]);
        W5500_Write(Sn_DIPR1(s), addr[1]);
        W5500_Write(Sn_DIPR2(s), addr[2]);
        W5500_Write(Sn_DIPR3(s), addr[3]);
        W5500_Write(Sn_DPORT0(s), (uint8_t) ((port & 0xff00) >> 8));
        W5500_Write(Sn_DPORT1(s), (uint8_t) (port & 0x00ff));
        W5500_Write(Sn_CR(s), Sn_CR_CONNECT);
        /* wait for completion */
        while (W5500_Read(Sn_CR(s)));

        while (W5500_Read(Sn_SR(s)) != SOCK_SYNSENT) {
            if (W5500_Read(Sn_SR(s)) == SOCK_ESTABLISHED) {
                break;
            }
            if (getSn_IR(s) & Sn_IR_TIMEOUT) {
                W5500_Write(Sn_IR(s), (Sn_IR_TIMEOUT)); // clear TIMEOUT Interrupt
                ret = 0;
                break;
            }
            if (getSn_IR(s) & Sn_IR_DISCON) { // clear dis connect Interrupt
                disconnect(s);
                ret = 0;
                break;
            }
        }
    }

    return ret;
}

/**
 *@brief   This function used for disconnect the socket s
 *@param		s: socket number.
 *@return  1 for success else 0.
 */
void disconnect(SOCKET s) {
    W5500_Write(Sn_CR(s), Sn_CR_DISCON);

    /* wait to process the command... */
    while (W5500_Read(Sn_CR(s)));
    /* ------- */
}

/**
 *@brief   This function used to send the data in TCP mode
 *@param		s: socket number.
 *@param		buf: data buffer to send.
 *@param		len: data length.
 *@return  1 for success else 0.
 */
uint16_t send(SOCKET s, const uint8_t *buf, uint16_t len) {
    uint8_t status = 0;
    uint16_t ret = 0;
    uint16_t freesize = 0;
    if (len > SSIZE[s])
        ret = SSIZE[s]; // check size not to exceed MAX size.
    else
        ret = len;

    // if freebuf is available, start.
    do {
        freesize = getSn_TX_FSR(s);
        status = W5500_Read(Sn_SR(s));
        if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT)) {
            ret = 0;
            break;
        }
    } while (freesize < ret);

    // copy data
    send_data_processing(s, (uint8_t *) buf, ret);
    W5500_Write(Sn_CR(s), Sn_CR_SEND);

    /* wait to process the command... */
    while (W5500_Read(Sn_CR(s)));

    while ((W5500_Read(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK) {
        status = W5500_Read(Sn_SR(s));
        if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT)) {
            //			printf("SEND_OK Problem!!\r\n");
            close(s);
            return 0;
        }
    }
    W5500_Write(Sn_IR(s), Sn_IR_SEND_OK);

#ifdef __DEF_IINCHIP_INT__
    putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
#else
    W5500_Write(Sn_IR(s), Sn_IR_SEND_OK);
#endif

    return ret;
}

/**
*@brief		This function is an application I/F function which is used to
receive the data in TCP mode. It continues to wait for data as much as the
application wants to receive.
*@param		s: socket number.
*@param		buf: data buffer to receive.
*@param		len: data length.
*@return  received data size for success else 0.
*/
uint16_t recv(SOCKET s, uint8_t *buf, uint16_t len) {
    uint16_t ret = 0;
    if (len > 0) {
        recv_data_processing(s, buf, len);
        W5500_Write(Sn_CR(s), Sn_CR_RECV);
        /* wait to process the command... */
        while (W5500_Read(Sn_CR(s)));
        /* ------- */
        ret = len;
    }
    return ret;
}

/**
*@brief   This function is an application I/F function which is used to send the
data for other then TCP mode. Unlike TCP transmission, The peer's destination
address and the port is needed.
*@param		s: socket number.
*@param		buf: data buffer to send.
*@param		len: data length.
*@param		addr: IP address to send.
*@param		port: IP port to send.
*@return  This function return send data size for success else 0.
*/
uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port) {
    uint16_t ret = 0;

    if (len > SSIZE[s])
        ret = SSIZE[s]; // check size not to exceed MAX size.
    else
        ret = len;

    if (((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
        ((port == 0x00))) //||(ret == 0) )
    {
        /* added return value */
        ret = 0;
    } else {
        W5500_Write(Sn_DIPR0(s), addr[0]);
        W5500_Write(Sn_DIPR1(s), addr[1]);
        W5500_Write(Sn_DIPR2(s), addr[2]);
        W5500_Write(Sn_DIPR3(s), addr[3]);
        W5500_Write(Sn_DPORT0(s), (uint8_t) ((port & 0xff00) >> 8));
        W5500_Write(Sn_DPORT1(s), (uint8_t) (port & 0x00ff));
        // copy data
        send_data_processing(s, (uint8_t *) buf, ret);
        W5500_Write(Sn_CR(s), Sn_CR_SEND);
        /* wait to process the command... */
        while (W5500_Read(Sn_CR(s)));
        /* ------- */
        while ((W5500_Read(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK) {
            if (W5500_Read(Sn_IR(s)) & Sn_IR_TIMEOUT) {
                /* clear interrupt */
                W5500_Write(Sn_IR(s), (Sn_IR_SEND_OK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
                return 0;
            }
        }
        W5500_Write(Sn_IR(s), Sn_IR_SEND_OK);
    }
    return ret;
}

/**
*@brief   This function is an application I/F function which is used to receive
the data in other then TCP mode. This function is used to receive UDP, IP_RAW
and MAC_RAW mode, and handle the header as well.
*@param		s: socket number.
*@param		buf: data buffer to receive.
*@param		len: data length.
*@param		addr: IP address to receive.
*@param		port: IP port to receive.
*@return	This function return received data size for success else 0.
*/
uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port) {
    uint8_t head[8];
    uint16_t data_len = 0;
    uint16_t ptr = 0;
    uint32_t addrbsb = 0;
    if (len > 0) {
        ptr = W5500_Read(Sn_RX_RD0(s));
        ptr = ((ptr & 0x00ff) << 8) + W5500_Read(Sn_RX_RD1(s));
        addrbsb = (uint32_t) (ptr << 8) + (s << 5) + 0x18;

        switch (W5500_Read(Sn_MR(s)) & 0x07) {
            case Sn_MR_UDP:
                W5500_Read_Buf(addrbsb, head, 0x08);
                ptr += 8;
                // read peer's IP address, port number.
                addr[0] = head[0];
                addr[1] = head[1];
                addr[2] = head[2];
                addr[3] = head[3];
                *port = head[4];
                *port = (*port << 8) + head[5];
                data_len = head[6];
                data_len = (data_len << 8) + head[7];

                addrbsb = (uint32_t) (ptr << 8) + (s << 5) + 0x18;
                W5500_Read_Buf(addrbsb, buf, data_len);
                ptr += data_len;

                W5500_Write(Sn_RX_RD0(s), (uint8_t) ((ptr & 0xff00) >> 8));
                W5500_Write(Sn_RX_RD1(s), (uint8_t) (ptr & 0x00ff));
                break;
            case Sn_MR_IPRAW:
                W5500_Read_Buf(addrbsb, head, 0x06);
                ptr += 6;
                addr[0] = head[0];
                addr[1] = head[1];
                addr[2] = head[2];
                addr[3] = head[3];
                data_len = head[4];
                data_len = (data_len << 8) + head[5];

                addrbsb = (uint32_t) (ptr << 8) + (s << 5) + 0x18;

                //		printf(" data:%d \r\n",data_len);
                W5500_Read_Buf(addrbsb, buf, data_len);

                ptr += data_len;

                W5500_Write(Sn_RX_RD0(s), (uint8_t) ((ptr & 0xff00) >> 8));
                W5500_Write(Sn_RX_RD1(s), (uint8_t) (ptr & 0x00ff));

                break;

            case Sn_MR_MACRAW:
                W5500_Read_Buf(addrbsb, head, 0x02);
                ptr += 2;
                data_len = head[0];
                data_len = (data_len << 8) + head[1] - 2;
                if (data_len > 1514) {
                    //					printf("data_len over 1514\r\n");
                    while (1);
                }

                addrbsb = (uint32_t) (ptr << 8) + (s << 5) + 0x18;
                W5500_Read_Buf(addrbsb, buf, data_len);
                ptr += data_len;

                W5500_Write(Sn_RX_RD0(s), (uint8_t) ((ptr & 0xff00) >> 8));
                W5500_Write(Sn_RX_RD1(s), (uint8_t) (ptr & 0x00ff));
                break;

            default:
                break;
        }
        W5500_Write(Sn_CR(s), Sn_CR_RECV);

        /* wait to process the command... */
        while (W5500_Read(Sn_CR(s)));
        /* ------- */
    }
    return data_len;
}

/**
 * @brief tcp client
 * @param s
 * @param remote_ip  服务器地址
 * @param remote_port 服务器端口
 * @return
 */
bool do_tcp_connect(SOCKET s, uint8_t *remote_ip, uint16_t remote_port) {
    if (getSocketStatus(s) == SOCK_ESTABLISHED) {
        return true;
    }
    switch (getSocketStatus(s)) /*获取socket的状态*/
    {
        case SOCK_CLOSED: /*socket处于关闭状态*/
            socket(s, Sn_MR_TCP, TCP_CLIENT_LISTEN_PORT, Sn_MR_ND);
            break;
        case SOCK_INIT: /*socket处于初始化状态*/
            if (connect(s, remote_ip, remote_port) == 1) {
                return true;
            } /*socket连接服务器*/
            break;
        case SOCK_CLOSE_WAIT: /*socket处于等待关闭状态*/
            disconnect(s);
            close(s);
            break;
        default:
            break;
    }
    return false;
}

/**
 * @brief tcp 发送数据
 * @param s
 * @param net_data
 * @return
 */
bool do_tcp_send(SOCKET s, Net_Data_t *net_data) {
    switch (getSocketStatus(s)) {
        case SOCK_ESTABLISHED:    /*socket处于连接建立状态*/
            clearSocketFlag(s); // 清除接收中断标志位
            uint16_t len = send(s, net_data->buf, net_data->buf_len);
            if (len != net_data->buf_len) {
                return false;
            }
    }
    return true;
}

/****************************************************************
 * @description: 发送字节数组
 * @param {SOCKET} s
 * @param {uint8_t} *buf
 * @param {uint16_t} buf_len
 * @return {*}
 ******************************************************************/
bool do_tcp_send_buf(SOCKET s, uint8_t *buf, uint16_t buf_len) {
    switch (getSocketStatus(s)) {
        case SOCK_ESTABLISHED:    /*socket处于连接建立状态*/
            clearSocketFlag(s); // 清除接收中断标志位
            uint16_t len = send(s, buf, buf_len);
            if (len != buf_len) {
                return false;
            }
    }
    return true;
}

/**
 * @brief tcp 发射字符串
 * @param s
 * @param str
 * @return
 */
bool do_tcp_send_str(SOCKET s, char *str) {
    if (getSocketStatus(s) == SOCK_ESTABLISHED) {
        /*socket处于连接建立状态*/
        clearSocketFlag(s); // 清除接收中断标志位
        uint16_t len = send(s, str, strlen(str));
        if (len != strlen(str)) {
            return false;
        }
    }
    return true;
}

/**
 * @brief tcp 接收数据
 * @param s socket
 * @param net_data
 * @return
 */
bool do_tcp_receive(SOCKET s, Net_Data_t *net_data) {
    switch (getSocketStatus(s)) /*获取socket的状态*/
    {
        case SOCK_ESTABLISHED:                       /*socket处于连接建立状态*/
            clearSocketFlag(s);                       // 清除接收中断标志位
            uint16_t len = getSocketRecDataLen(s); /*定义len为已接收数据的长度*/
            if (len > 0) {
                recv(s, net_data->buf, len);
                net_data->buf_len = len; /*接收来自Server的数据*/
                return true;
            }
            break;
        default:
            break;
    }
    return false;
}

/**
 * @brief udp 服务
 * @param s
 * @param net_conn 接收远端连接的地址地址和端口
 * @param net_data 接收远端传过来的数据
 * @return
 */
bool do_udp_listen(SOCKET s, uint16_t listen_port, Net_Conn_t *net_conn, Net_Data_t *net_data) {
    uint16_t len;
    switch (getSocketStatus(s)) /*获取socket的状态*/
    {
        case SOCK_CLOSED:                                     /*socket处于关闭状态*/
            socket(s, Sn_MR_UDP, listen_port, 0); /*初始化socket*/
            break;
        case SOCK_UDP: /*socket初始化完成*/
            clearSocketFlag(s);
            if ((len = getSocketRecDataLen(s)) > 0) /*接收到数据*/
            {
                recvfrom(s, net_data->buf, len, net_conn->ip, &net_conn->port); /*W5500接收计算机发送来的数据*/
                net_data->buf_len = len - 8;
                net_data->buf[net_data->buf_len] = 0x00;
                return true; /*添加字符串结束符*/
            }
            break;
    }
    return false;
}

/**
 * @brief udp 发送数据
 * @param s
 * @param net_conn 目标地址
 * @param net_data 发送的数据
 * @return 结果
 */
bool do_udp_send(SOCKET s, Net_Conn_t *net_conn, Net_Data_t *net_data) {
    uint8_t status = getSocketStatus(s);
    if (status == SOCK_UDP) {
        clearSocketFlag(s); /*清接收中断*/
        uint16_t len = sendto(s, net_data->buf, net_data->buf_len, net_conn->ip, net_conn->port);
        if (len == net_data->buf_len) {
            return true;
        }
    } else if (status == SOCK_CLOSED) {
        socket(s, Sn_MR_UDP, UDP_CLIENT_LISTEN_PORT, 0);
    }
    return false;
}

bool udp_socket_init(SOCKET s, uint16_t local_port) {
//	if (udp_socket_status(s) != SOCK_UDP) {
//		return socket(s, Sn_MR_UDP, local_port, 0) == 1 ? true : false;
//	}
    udp_local_port = local_port;
    socket(s, Sn_MR_UDP, udp_local_port, 0);
    return true;
}

uint8_t udp_socket_status(SOCKET s) {
    return getSocketStatus(s);
}

bool udp_send(SOCKET s, uint8_t *dst_ip, uint16_t dst_port, uint8_t *data, uint16_t len) {
    clearSocketFlag(s); /*清接收中断*/
    if (udp_socket_status(s) != SOCK_UDP) {
        socket(s, Sn_MR_UDP, udp_local_port, 0);
    }
    return sendto(s, data, len, dst_ip, dst_port) == len ? true : false;
}

bool udp_rec(SOCKET s, uint16_t listen_port, uint8_t *dstIp, uint16_t *dstPort, uint8_t *recData, uint16_t *recLen) {
    uint16_t len;
    switch (getSocketStatus(s)) /*获取socket的状态*/
    {
        case SOCK_CLOSED:                                     /*socket处于关闭状态*/
            socket(s, Sn_MR_UDP, listen_port, 0); /*初始化socket*/
            break;
        case SOCK_UDP: /*socket初始化完成*/
            clearSocketFlag(s);
            if ((len = getSocketRecDataLen(s)) > 0) /*接收到数据*/
            {
                recvfrom(s, recData, len, dstIp, dstPort); /*W5500接收计算机发送来的数据*/
                *recLen = len;
                recData[len] = 0x00;
                return true; /*添加字符串结束符*/
            }
            break;
    }
    return false;
}

uint16_t tcp_client_port = 1225;

uint8_t tcp_client_status(SOCKET s) {
    return getSocketStatus(s);
}


void tcp_client_connect(SOCKET s, uint8_t *dst_ip, uint16_t dst_port) {
    uint8_t status = tcp_client_status(s);
    if (status == SOCK_CLOSE_WAIT) {
        disconnect(s);
        close(s);
        status = tcp_client_status(s);
        w5500_ps("close socket\r\n");
    }
    if (status == SOCK_CLOSED) {
        socket(s, Sn_MR_TCP, tcp_client_port++, Sn_MR_ND);
        status = tcp_client_status(s);
        w5500_ps("build socket\r\n");
    }
    if (status == SOCK_INIT) {
        connect(s, dst_ip, dst_port);
        w5500_ps("connect\r\n");
    }
}

bool tcp_client_send(SOCKET s, uint8_t *data, uint16_t len) {

    if (tcp_client_status(s) == SOCK_ESTABLISHED) {
        send(s, data, len);
        return true;
    }
    return false;
}


/**
 * @brief 初始化tcp server 接口
 * @param s
 * @param listen_port
 * @param buf
 * @param buf_len
 */
void tcp_server_init(SOCKET s, uint16_t listen_port, Net_Data_t *netData) {
    socket_port[s] = listen_port;
    socket_net_data[s] = netData;
    // 关闭上次的socket
    disconnect(s);
    close(s);
}

Net_Data_t *tcp_server_listen(SOCKET s) {
    uint8_t status = getSocketStatus(s);
    socket_net_data[s]->buf_len = 0;
    if (status == SOCK_CLOSE_WAIT) {

        disconnect(s);
        close(s);
    } else if (status == SOCK_CLOSED || status == SOCK_UDP) {
        socket(s, Sn_MR_TCP, socket_port[s], Sn_MR_ND); /*打开socket*/
    } else if (status == SOCK_INIT) {
        listen(s);    /*socket建立监听*/
    } else if (status == SOCK_ESTABLISHED) {
        clearSocketFlag(s);                       // 清除接收中断标志位
        uint16_t len = getSocketRecDataLen(s); /*定义len为已接收数据的长度*/
        if (len > 0) {
            memset(socket_net_data[s]->buf, 0, socket_net_data[s]->buf_len);
            recv(s, socket_net_data[s]->buf, len); /*接收来自Client的数据*/
        } else {
            // 检查芯片处于连接状态,但网线已断开时,自动释放端口,避免下次无法连接
            if ((W5500_Read(PHYCFGR) & 0x1) == 0) {

                close(s);
            }
        }
        socket_net_data[s]->buf_len = len;
        return socket_net_data[s];
    } else {

    }
    return socket_net_data[s];
}

/**
 * @brief
 * @param s
 * @param listen_port
 * @param net_data 存储接收的数据
 * @return 有客户端连接:true; 没有: false
 */
bool tcp_listen(SOCKET s, uint16_t listen_port, Net_Data_t *net_data) {

    switch (getSocketStatus(s)) /*获取socket的状态*/
    {
        case SOCK_CLOSED:                                 /*socket处于关闭状态*/
            socket(s, Sn_MR_TCP, listen_port, Sn_MR_ND); /*打开socket*/
            break;
        case SOCK_INIT: /*socket已初始化状态*/
            listen(s);    /*socket建立监听*/
            break;
        case SOCK_ESTABLISHED:                       /*socket处于连接建立状态*/
            clearSocketFlag(s);                       // 清除接收中断标志位
            uint16_t len = getSocketRecDataLen(s); /*定义len为已接收数据的长度*/
            if (len > 0) {
//				w5500_ps("rec pc order len222:%d\r\n",len);
                memset(net_data, 0, net_data->buf_len);
                net_data->buf_len = len;
                recv(s, net_data->buf, len); /*接收来自Client的数据*/
                return true;
            }
            break;
        case SOCK_CLOSE_WAIT: /*socket处于等待关闭状态*/
            disconnect(s);
            close(s);
            break;
    }
    return false;
}

void tcp_server_resp(SOCKET s, uint8_t *data, uint16_t len) {
    send(s, data, len);
}

与外设相关的接口实现

头文件

#ifndef STM32F103VET6_PROJECT_W5500_PORT_H
#define STM32F103VET6_PROJECT_W5500_PORT_H

#include "sys_core.h"

__weak void W5500_Driver_MspInit(void);

__weak void W5500_RST_HIGH(void);

__weak void W5500_RST_LOW(void);

__weak void W5500_CS_LOW(void);

__weak void W5500_CS_HIGH(void);

__weak uint8_t W5500_SPI_WritByte(uint8_t dat);

#endif //STM32F103VET6_PROJECT_W5500_PORT_H

示例(这里使用的SPI3)

#include "app_gb_conf.h"
#include "w5500_port.h"
#include "w5500_config.h"
#include "spi.h"

void data_load_net(void) {

}

void driver_handle_net(void) {
    W5500_Driver_MspInit();
}

void soft_handle_net(void) {
    Net_Reset();
    Net_Config_Set(&Default_Net_Config);
    os_ps("app  net soft_handle_net\r\n");
}


/***********************************************W5500驱动实现**********************************************/
void W5500_Driver_MspInit(void) {
    // 使能引脚
    GPIO_INIT(GPIOB, GPIO_PIN_12 | GPIO_PIN_11, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW);
    SPI3_Init(SPI_POLARITY_LOW, SPI_PHASE_1EDGE);
}

void W5500_RST_HIGH(void) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
}

void W5500_RST_LOW(void) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);

}

void W5500_CS_LOW(void) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
}

void W5500_CS_HIGH(void) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
}

uint8_t W5500_SPI_WritByte(uint8_t dat) {
    uint8_t data = 0;
    HAL_SPI_TransmitReceive(&spi3_handle, &dat, &data, 1, 10);
    return data;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
c 环境配置 colin 主要包括三个步骤:安装编译器、配置环境变量和测试编译器。 首先,安装编译器。在安装 c 环境之前,我们需要先下载对应的编译器软件。常用的 c 编译器有 gcc、clang、MSVC 等。根据个人需求选择适合自己的编译器,并下载对应的安装包。然后,按照安装向导进行安装即可。安装完成后,我们就拥有了一个可用的 c 编译器。 接下来,配置环境变量。环境变量的配置可以使得我们在任意目录下都能够直接使用 c 编译器。首先,找到我们安装的编译器安装目录。然后,将该目录添加到系统的环境变量中。具体的配置步骤可以根据操作系统的不同而有所差异,但一般都是在控制面板或者系统设置中找到“环境变量”选项,然后添加编译器安装目录到系统的“PATH”变量中。配置完成后,我们就可以在任意目录下打开命令行终端,输入编译器命令来编译和运行 c 程序。 最后,测试编译器。经过以上两个步骤的配置,我们就可以测试我们的 c 编译器是否正常工作了。在任意目录下新建一个文本文件,将其后缀改为“.c”,比如“test.c”。然后,用任意文本编辑器打开该文件,输入一段简单的 c 代码,比如“#include <stdio.h> int main(){ printf("Hello, world!"); return 0; }”。保存文件后,回到命令行终端,进入该文件所在的目录,输入编译命令,如“gcc test.c -o test”,然后按回车键进行编译。如果没有出现错误信息,说明我们的 c 编译器已经成功配置。 综上所述,通过安装编译器、配置环境变量和测试编译器三个步骤,我们可以完成 c 环境的配置,从而能够顺利编译和运行 c 程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

詩不诉卿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值