STM32F103+W5500的ping实验+TCP/IP+UDP实验
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 配置寄存器)
更多推荐



所有评论(0)