1.W5500基本介绍

        这里不做详细硬件介绍,只描述关键的软件编程硬件部分。

1.W5500 提供了 SPI(串行外部接口)作为外设主机接口,共有 SCSn, SCLK, MOSI, MISO 4 路信 号,且作为 SPI 从机工作。也就是使用时,只需要连接SPI通讯即可

2.根据其工作模式(可变数据长度模 式/固定数据长 度模式),其中使用可变数据长度时,SPI按规则连接,4根信号线保持正常连接即可。当使用固定数据长度时,CS端口接GND,此时SPI只能连接W5500一个从机,且数据长度固定。这里使用可变数据长度

3.W5500 支持 SPI 模式 0 及模式 3。W5500 的 SPI 数据帧包括了 16 位地址段的偏移地址,8 位控制段和 N 字节数据段。 

2.以太网基本配置

        这里有必要记录一下配置问题,之前在这里设置不对导致一直ping不通。我使用的网线是568A+568B这是个交叉线,它可以直接让W5500和PC连接,不需要使用网关或交换器。根据搜索资料,W5500是不具备交换自动交换线序的功能。但现在电脑网卡可能有交换功能,如果使用普通网线,那可能需要经过一个网关。也可能不使用,如果ping不通可以尝试换根网线。

//定义w5500的IP地址,mac地址,子网掩码,网关地址  均为8位10进制 <255

1. IP地址:电脑设置的本地IP地址是192,168,1,43。W5500的IP地址是192,168,1,199最后一位随便设置,只要保证和电脑在同一个网段就可以。IPV4地址是4个字节

2. MAC地址:0x0c,0x29,0xab,0x7c,0x00,0x01。和电脑的不同,MAC地址是6个字节  第1个字节的二进制最后2位应该是10 其余5个十进制自由设置

3.子网掩码:255,255,255,0

4.网关地址:192,168,1,1 和电脑一致

3.软件编写流程介绍

1.注册自定义回调函数 user_register_function();

2.初始化SPI             MySPI_Init();

3.重置w5500            W5500_reset();

4.设置mac地址         W5500_SetMacAddress();

5.设置IP地址,子网掩码,网关地址        W5500_SetIP();

2.W5500的ping实验

#include "MyW5500.h"
#include "MySPI.h"
#include "wizchip_conf.h"
#include "Delay.h"
#include <stdio.h>
//定义w5500的IP地址,mac地址,子网掩码,网关地址  均为8位10进制 <255
uint8_t IP_address[4]={192,168,1,199};             //IPV4地址是4个字节     最后1个字节十进制自由设置
uint8_t mac_address[6]={0x0c,0x29,0xab,0x7c,0x00,0x01};   //MAC地址是6个字节  第1个字节的二进制最后2位应该是10 其余5个十进制自由设置
uint8_t subnet_mask[4]={255,255,255,0};             //子网掩码
uint8_t gateway_address[4]={192,168,1,1};          //网关地址

static void W5500_reset(); //重置w5500
static void W5500_SetMacAddress(); //设置mac地址
static void W5500_SetIP(); //设置IP地址,子网掩码,网关地址

void MyW5500_Init()
{    
    //1.注册自定义回调函数
    user_register_function();
   //2.初始化SPI
   MySPI_Init();
   //3.重置w5500
   W5500_reset();
   //4.设置mac地址
   W5500_SetMacAddress();
   //5.设置IP地址,子网掩码,网关地址
   W5500_SetIP();
}

void W5500_reset()
{	
   GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
 	GPIO_ResetBits(GPIOC, GPIO_Pin_15);
	Delay_ms(50);
	GPIO_SetBits(GPIOC, GPIO_Pin_15);
	Delay_ms(200);
}
void W5500_SetMacAddress() //设置mac地址
{
   // printf("W5500_SetMacAddress\n"); 
    setSHAR(mac_address);
   // printf("W5500_SetMacAddress done\n");
}

void W5500_SetIP() //设置IP地址,子网掩码,网关地址
{
   // printf("W5500_SetIP\n"); 
    setSIPR(IP_address);   
    setSUBR(subnet_mask);
    setGAR(gateway_address);
   // printf("W5500_SetIP done\n");
}
int main(void)
{	
	Serial_Init();
	
	MyW5500_Init();
	//printf("W5500 Init done\n");
	
	while(1)
	{	

	}
}

执行到此,打开搜索输入CMD进入命令提示框,输入ping + W5500的IP地址 

这里示例我是用的本机IP,如果ping通也应该是这个样子。

3.W5500的服务器搭建SERVER

1.搭建一个服务器,任何的客户端都可以连接它。

#include "TCP.h"
#include <stdio.h>
#include "Serial.h"


//定义全局变量 保存客户端IP和端口 
uint8_t ClientIP[4];
uint16_t ClientPort=0;

/**
 * @brief TCP服务器启动函数
 * 
 * 该函数实现W5500芯片的TCP服务器状态机管理,通过轮询Socket状态
 * 实现TCP连接的建立和管理流程。需要在主循环中周期性调用此函数。
 * 
 * TCP服务器状态转换流程:
 * SOCK_CLOSED -> SOCK_INIT -> SOCK_LISTEN -> SOCK_ESTABLISHED -> SOCK_CLOSE_WAIT -> SOCK_CLOSED
 * 
 * @note 此函数为非阻塞调用,每次调用只处理当前状态并返回
 */
void TCP_SERVER_Start(void)
{
    //1.获取Socket状态
    uint8_t status = getSn_SR(Socket);
    //2.判断当前状态执行相应操作,进入下一个状态
    if(status == SOCK_CLOSED)
    {
        //2.1 如果是关闭状态就打开Socket 配置TCP port ACK不延时
        int8_t n=socket(Socket,Sn_MR_TCP,8888,SF_TCP_NODELAY);
        if(n==Socket) //返回值为当前socket号 成功
        {
            //2.2 打开成功,监听连接
        }
        else
        {
            //2.2 打开失败,错误码为n
        }
    }
    //3.端口打开并处于TCP工作模式
    else if (status==SOCK_INIT)
    {
        //3.1 监听连接 启动服务器
       int8_t n=listen(Socket);
       if(n==SOCK_OK)
       {
            //3.2 监听成功,等待连接
       }
       else
       {
            //3.2 监听失败,错误码为n
       }
    }
    //4.端口处于监听状态
     else if (status==SOCK_LISTEN)
    {
        //4.1 等待连接
    }

    //5.端口处于已连接 等待数据
     else if (status==SOCK_ESTABLISHED)
    {
       // 读取客户端IP和端口 只读取1次 
        if(getSn_IR(Socket) & Sn_IR_CON)
        {           
            getSn_DIPR(Socket,ClientIP);//读取客户端IP
            ClientPort=getSn_DPORT(Socket);//读取客户端端口
        //    printf("连接成功ClientIP %d.%d.%d.%d,ClientPort %d\n",
         //       ClientIP[0],ClientIP[1],ClientIP[2],ClientIP[3],ClientPort);
         Serial_SendArray(ClientIP,4);
        // Serial_SendByte(ClientPort>>8);
        // Serial_SendByte(ClientPort);
            setSn_IR(Socket,Sn_IR_CON); //清零事件标志位
        }


        //5.1 连接成功,等待数据
    }

    //6.如果是半关闭状态 
     else if (status==SOCK_CLOSE_WAIT)
    {
        //6.1 彻底关闭 并重新循环
        close(Socket);
    }
}
    

//接收数据
void TCP_SERVER_Receive(uint8_t *data, uint16_t *len)//maxlen=16k=16384<65536
{
    //1.获取Socket状态
    uint8_t status = getSn_SR(Socket);
    //2.如果是已连接状态,接收数据
    if(status == SOCK_ESTABLISHED)
    {   
        //根据事件标志位判断是否有数据可读
        if(getSn_IR(Socket) & Sn_IR_RECV)
        {
            //清零事件标志位 //置1清零
            setSn_IR(Socket,Sn_IR_RECV);
            //读取数据长度
            *len = getSn_RX_RSR(Socket);
            //读取数据
            recv(Socket,data,*len);
        }   
    }
}


//发送数据
void TCP_SERVER_Send(uint8_t *data, uint16_t len)
{
   //1.获取Socket状态
    uint8_t status = getSn_SR(Socket);
    //2.如果是已连接状态,发送数据
    if(status == SOCK_ESTABLISHED)
    {
       send(Socket,data,len);
    }
}

分析:

1.Sn3_MR (Socket n 模式寄存器)

该寄存器用于配置所有 SOCKET 的选项或协议类型 W5500有8个socket 可以理解成有8个port 。 这里需要配置第5位 使用无延时Delay和第0~3bit 选择TCP模式

2.Sn_CR (Socket n 配置寄存器)

该寄存器用于设置 Socket n 的配置命令如 OPENCLOSECONNECTLISTENEND
RECEIVE
后续内容有时间再更新
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐