#stm32驱动外设模块总结w5500模块

1简介

2硬件连接

3软件编程

3.1 初始化

3.1.1 SPI初始化

这里注意配置 设置为全双工模式、主机SPI、8为数据模式、工作模式0 片选由外部引脚管理,设置预分频值为2 、高位先行、CRC多项式为7 使能SPI

void W5500_SPI1_Configuration(void)
{
    GPIO_InitTypeDef 	GPIO_InitStructure;
    SPI_InitTypeDef   	SPI_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);

    /* 初始化SCK、MISO、MOSI引脚 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);

    /* 初始化CS引脚 */
    GPIO_InitStructure.GPIO_Pin = W5500_SCS;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(W5500_SCS_PORT, &GPIO_InitStructure);
    GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);

    /* 初始化配置STM32 SPI1 */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	//SPI设置为双线双向全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;							//设置为主SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;						//SPI发送接收8位帧结构
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;							//时钟悬空低
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;							//数据捕获于第1个时钟沿
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;								//NSS由外部管脚管理
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;	//波特率预分频值为2
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;					//数据传输从MSB位开始
    SPI_InitStructure.SPI_CRCPolynomial = 7;								//CRC多项式为7
    SPI_Init(SPI1, &SPI_InitStructure);									//根据SPI_InitStruct中指定的参数初始化外设SPI1寄存器

    SPI_Cmd(SPI1, ENABLE);	//STM32使能SPI1
}

3.1.2 SPI初始化GPIO设置初始化

这里指的是RST INT引脚的初始化
RST配置为推完输出
INT设置为上拉输入
开启外部中断0,模式为中断模式下降沿触发 中断线使能,
配置中断优先级为0,0最高了

void W5500_GPIO_Configuration(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    EXTI_InitTypeDef  EXTI_InitStructure;
	  NVIC_InitTypeDef  NVIC_InitStructure;
	
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA , ENABLE);

    /* W5500_RST引脚初始化配置(PA0) */
    GPIO_InitStructure.GPIO_Pin  = W5500_RST;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(W5500_RST_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(W5500_RST_PORT, W5500_RST);

    /* W5500_INT引脚初始化配置(PB1) */
    GPIO_InitStructure.GPIO_Pin = W5500_INT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(W5500_INT_PORT, &GPIO_InitStructure);

    /* Connect EXTI Line1 to PB0 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);

    /* PB1 as W5500 interrupt input */
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
		
    //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);		
		
}

3.2 装载网络参数

将本地(本地MCU对应的)IP、目标(服务器的)IP、子网掩码(我不知道子网掩码的具体作用,IPV4这里可以设置为255.255.255.0(0xFFFFFF00))、网关(192.168.1.1)、DNS(192.168.1.1)、物理地址(MAC地址是由stm32的序列号得来的)、本机端口、目标端口

u8 Gateway_IP[4];//网关IP地址
u8 Sub_Mask[4];	//子网掩码
u8 Phy_Addr[6];	//物理地址(MAC)
u8 IP_Addr[4];	//本机IP地址
u8 DNS[4];	//DNS

u8 S0_Port[2];	//端口0的端口号(5000)
u8 S0_DIP[4];	//端口0目的IP地址
u8 S0_DPort[2];	//端口0目的端口号(6000)
void Load_Net_Parameters(void)//加载网关参数
{
    IP_Addr[0] = (PNetData->Local_IP & 0xFF000000) >> 24; //加载本机IP地址
    IP_Addr[1] = (PNetData->Local_IP & 0x00FF0000) >> 16;
    IP_Addr[2] = (PNetData->Local_IP & 0x0000FF00) >> 8;
    IP_Addr[3] = (PNetData->Local_IP & 0x000000FF);

    S0_DIP[0] = (PNetData->Dest_IP & 0xFF000000) >> 24; //加载端口0的目的IP地址
    S0_DIP[1] = (PNetData->Dest_IP & 0x00FF0000) >> 16;
    S0_DIP[2] = (PNetData->Dest_IP & 0x0000FF00) >> 8;
    S0_DIP[3] = (PNetData->Dest_IP & 0x000000FF);

    Sub_Mask[0] = (PNetData->SubMask & 0xFF000000) >> 24; //加载子网掩码
    Sub_Mask[1] = (PNetData->SubMask & 0x00FF0000) >> 16;
    Sub_Mask[2] = (PNetData->SubMask & 0x0000FF00) >> 8;
    Sub_Mask[3] = (PNetData->SubMask & 0x000000FF);

    Gateway_IP[0] = (PNetData->GateWay & 0xFF000000) >> 24;
    Gateway_IP[1] = (PNetData->GateWay & 0x00FF0000) >> 16;
    Gateway_IP[2] = (PNetData->GateWay & 0x0000FF00) >> 8;
    Gateway_IP[3] = (PNetData->GateWay & 0x000000FF);

    DNS[0] = (PNetData->DNS & 0xFF000000) >> 24;
    DNS[1] = (PNetData->DNS & 0x00FF0000) >> 16;
    DNS[2] = (PNetData->DNS & 0x0000FF00) >> 8;
    DNS[3] = (PNetData->DNS & 0x000000FF);

    Phy_Addr[0] = (PNetData->MAC_Addr1 & 0xFF00) >> 8; //加载物理地址
    Phy_Addr[1] = (PNetData->MAC_Addr1 & 0x00FF);
    Phy_Addr[2] = (PNetData->MAC_Addr2 & 0xFF00) >> 8;
    Phy_Addr[3] = (PNetData->MAC_Addr2 & 0x00FF);
    Phy_Addr[4] = (PNetData->MAC_Addr3 & 0xFF00) >> 8;
    Phy_Addr[5] = (PNetData->MAC_Addr3 & 0x00FF);

    S0_Port[0] = (PNetData->S_PORT & 0xFF00) >> 8 ;//加载端口0的端口号5000
    S0_Port[1] = (PNetData->S_PORT & 0x00FF);

    S0_DPort[0] = (PNetData->D_PORT & 0xFF00) >> 8 ;//加载端口0的目的端口号8080
    S0_DPort[1] = PNetData->D_PORT & 0x00FF;

    S0_Mode = TCP_CLIENT; //加载端口0的工作模式,TCP客户端模式

}

3.3硬件复位w5500

低电平复位
在这里插入图片描述

void W5500_Hardware_Reset(void)
{
    u8 i = 0;
    GPIO_ResetBits(W5500_RST_PORT, W5500_RST);//复位引脚拉低
    delay_ms(50);
    //OSTimeDly(50);
    GPIO_SetBits(W5500_RST_PORT, W5500_RST);//复位引脚拉高
    delay_ms(200);
    //OSTimeDly(200);
    for(i = 0; i < 3; i++)
    {
        if((Read_W5500_1Byte(PHYCFGR) & LINK) == 1)
        {
            break;
        }
    }
    //	while((Read_W5500_1Byte(PHYCFGR) & LINK)==0);//等待以太网连接完成		读取W5500 PHY 配置寄存器 判断该字节最低位的连接状态
}	

片选拉低发送16位寄存器地址 PHYCFGR 0x002e
在这里插入图片描述
发送一帧数据的格式
在这里插入图片描述
这个用作寄存器地址
在这里插入图片描述
2.2.2是控制段这里不好截图就不接 7:3 选择哪个寄存器00000表示通用寄存器
2表示读写模式 0读 1写
1:0 OM表示SPI工作模式:这个和stm32上说的0123工作模式不是一个意思,这里指的是SPI 模式支持 2 种模式:可变数据长度模式和固定长度模式
可变数据长度模式(VDM):数据长度通过 SCSn 控制;
外设主机使 SCSn 信号拉低(高电平到低电平),并通知 W5500 SPI数据帧地址段的起始地址。然后外设主机传输控制段。此时,OM[1:0]=’00’。在 N 字节数据段传输完毕后,SCSn 信号拉高(低电平到高电平)且通知 W5500SPI 数据帧数据段的结束地址。在可变数据长度模式下,SCSn 必须通过外设主机通过 SPI 数据帧单元控制。(参见图 4)

  • 固定数据长度模式(FDM)
    : 在固定数据长度模式下,数据的长度通过 OM[1:0]位来设定,但是不能为‘00’。所以,SCSn 信号应该保持低电平状态,然后根据 OM[1:0]的值确定一种长度类型(介于 1 字节,2 字节,4 字节)
    在这里插入图片描述
    这里有点冲突我使用图4接法程序中用的却是1个固定字节
    2.2.3 数据段
    在 SPI 工作模式位 OM[1:0]设定了控制端之后,数据段被设定为 2 种长度类型:1 种为可变的 N 字节长度(可变数据长度模式),另以一种为确定的 1/2/4 字节长度(固定数据长度模式)。此时,1 字节数据从最大标志位到最小标志位,通过 MOSI 或者 MISO 信号传输。
    这里我理解是高位先行然后因为是全双工模式MISO先读一个数据,MOSI还得发一个假数据 然后再读了一下是怕数据出错吗?
    这里读的是寄存器PHYCFGR 0x002e 如果bit0=1表示链接成功
unsigned char Read_W5500_1Byte(unsigned short reg)
{
    unsigned char i;

    GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为低电平

    SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址
    SPI1_Send_Byte(FDM1 | RWB_READ | COMMON_R); //通过SPI1写控制字节,1个字节数据长度,读数据,选择通用寄存器

    i = SPI_I2S_ReceiveData(SPI1);
    SPI1_Send_Byte(0x00);//发送一个哑数据
    i = SPI_I2S_ReceiveData(SPI1); //读取1个字节数据

    GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);//置W5500的SCS为高电平
    return i;//返回读取到的寄存器数据
}

3.4设置寄存器初始化5500

Write_W5500_1Byte(MR, RST) 内部寄存器初始化
在这里插入图片描述
Write_W5500_nByte(GAR, Gateway_IP, 4); 写网关IP寄存器
在这里插入图片描述

Write_W5500_nByte(SUBR, Sub_Mask, 4); 写子网掩码寄存器
在这里插入图片描述

Write_W5500_nByte(SHAR, Phy_Addr, 6);写mac地址寄存器在这里插入图片描述
Write_W5500_nByte(SIPR, IP_Addr, 4);写本机IP(源IP)在这里插入图片描述
for(i = 0; i < 8; i++)
{
Write_W5500_SOCK_1Byte(i, Sn_RXBUF_SIZE, 0x02); //Socket Rx memory size=2k
Write_W5500_SOCK_1Byte(i, Sn_TXBUF_SIZE, 0x10); //Socket Tx mempry size=16k
}
配置每个socket的收发缓冲区分别为2K和16K
在这里插入图片描述
Write_W5500_2Byte(RTR, 0x07d0);设置重传超时时间
在这里插入图片描述

Write_W5500_1Byte(IMR, IM_IR7 | IM_IR6);//配置中断屏蔽寄存器
在这里插入图片描述
Write_W5500_1Byte(RCR, 8);//设置超时重发次数寄存器
在这里插入图片描述
Write_W5500_1Byte(SIMR, S0_IMR);设置socket中断屏蔽寄存器
在这里插入图片描述

Write_W5500_SOCK_1Byte(0, Sn_IMR, IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);//向socket0 的Sn_IMR寄存器写值

在这里插入图片描述

void W5500_Init_Reg(void)
{
    u8 i = 0;

    Write_W5500_1Byte(MR, RST);//软件复位W5500,置1有效 复位,复位后自动清0 模式寄存器用于S/W软件复位
    delay_ms(10);//延时10ms,自己定义该函数
    //OSTimeDly(10);
    //设置网关(Gateway)的IP地址,Gateway_IP为4字节unsigned char数组,自己定义
    //使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet
    Write_W5500_nByte(GAR, Gateway_IP, 4);

    //设置子网掩码(MASK)值,SUB_MASK为4字节unsigned char数组,自己定义
    //子网掩码用于子网运算
    Write_W5500_nByte(SUBR, Sub_Mask, 4);

    //设置物理地址,PHY_ADDR为6字节unsigned char数组,自己定义,用于唯一标识网络设备的物理地址值
    //该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号
    //如果自己定义物理地址,注意第一个字节必须为偶数
    Write_W5500_nByte(SHAR, Phy_Addr, 6);

    //设置本机的IP地址,IP_ADDR为4字节unsigned char数组,自己定义
    //注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关
    Write_W5500_nByte(SIPR, IP_Addr, 4);

    //设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册
    for(i = 0; i < 8; i++)
    {
        Write_W5500_SOCK_1Byte(i, Sn_RXBUF_SIZE, 0x02); //Socket Rx memory size=2k
        Write_W5500_SOCK_1Byte(i, Sn_TXBUF_SIZE, 0x10); //Socket Tx mempry size=16k
    }

    //设置重试时间,默认为2000(200ms)
    //每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒
    Write_W5500_2Byte(RTR, 0x07d0);

    //设置重试次数,默认为8次
    //如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)
    Write_W5500_1Byte(RCR, 8);

    //启动中断,参考W5500数据手册确定自己需要的中断类型
    //IMR_CONFLICT是IP地址冲突异常中断,IMR_UNREACH是UDP通信时,地址无法到达的异常中断
    //其它是Socket事件中断,根据需要添加
    Write_W5500_1Byte(IMR, IM_IR7 | IM_IR6);
    Write_W5500_1Byte(SIMR, S0_IMR);
    Write_W5500_SOCK_1Byte(0, Sn_IMR, IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);
}

3.5使用

W5500_Socket_Set();//W5500端口初始化配置 每次循环都要重新配置 主要是设置模式为TCP_CLIENT模式打开socket0 连接socket0
W5500端口初始化配置

   W5500_Socket_Set();//W5500端口初始化配置

S0_State 是个全局变量
初始化时加载网络参数 已经将S0_Mode 设置为TCP_CLIENT

void W5500_Socket_Set(void)
{
    if(S0_State == 0) //端口0初始化配置
    {
        if(S0_Mode == TCP_CLIENT) //TCP客户端模式
        {
            if(Socket_Connect(0) == TRUE)
            {
                S0_State = S_INIT;

            }
            else
                S0_State = 0;
        }
    }
}

Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); //设置socket为TCP模式
Sn_MR寄存器 socket 模式寄存器设置为TCP模式
Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); //打开Socket
Sn_CR (Socket n 配置寄存器) 设置为socket打开

Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INI
TCP模式下对应的Sn_SR值
Write_W5500_SOCK_1Byte(s, Sn_CR, CONNECT);
配为链接状态 在这里插入图片描述

unsigned char Socket_Connect(SOCKET s)
{
    Write_W5500_SOCK_1Byte(s, Sn_MR, MR_TCP); //设置socket为TCP模式
    Write_W5500_SOCK_1Byte(s, Sn_CR, OPEN); //打开Socket
    delay_ms(10);//延时5ms
    //	OSTimeDly(5);
    if(Read_W5500_SOCK_1Byte(s, Sn_SR) != SOCK_INIT) //如果socket打开失败
    {
        Write_W5500_SOCK_1Byte(s, Sn_CR, CLOSE); //打开不成功,关闭Socket
        return FALSE;//返回FALSE(0x00)
    }
    Write_W5500_SOCK_1Byte(s, Sn_CR, CONNECT); //设置Socket为Connect模式
    return TRUE;//返回TRUE,设置成功
}

获取信号量获取不到被挂起

  OSSemPend(W5500INTFLAG, 0, &err);

这个信号量会在终端中被释放 所以每当有中断 就会触发信号量释放 这个任务就会被就绪

void EXTI0_IRQHandler(void)
{
	OS_CPU_SR cpu_sr;
	OS_ENTER_CRITICAL();              // Tell uC/OS-II that we are starting an ISR    //
	OSIntNesting++;
	OS_EXIT_CRITICAL();
	if(EXTI_GetITStatus(EXTI_Line0) != RESET)
	{
		EXTI_ClearITPendingBit(EXTI_Line0);
		OSSemPost(W5500INTFLAG);
	}
	OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR       */
}

然后是中断处理
先看是什么中断
i = Read_W5500_1Byte(IR);//读取中断标志寄存器
再把中断清除由于只有高4位有用这里与上0xf0
Write_W5500_1Byte(IR, (i & 0xf0)); //回写清除中断标志
在这里插入图片描述
在这里插入图片描述
查看是不是socket中断
i = Read_W5500_1Byte(SIR); //读取端口中断标志寄存器
Write_W5500_SOCK_1Byte(0, SIR, i);//我觉的这写反了应该是 Write_W5500_1Byte( SIR, 0); 把SIR清零 而且这应该是写通用寄存器
在这里插入图片描述

后面才是查看socket寄存器

这里注意想把Sn_IR的某位清零就对这位写1 所以中断是谁就把谁写去

这里分了几种情况
1、连接成功中断
做一下处理 连接标识符写为1
断开时间归零
连接状态全局变量|上连接成功
网络状态指示灯关
2、断开连接中断
做一下处理 socket0断开连接标识符写为1
关闭socket0
初始化socket0
连接状态全局变量设置为连接失败
网络状态指示灯开
3、数据发送成功中断
复位接收与发送数据超时计数归零
socket0断开连接标识符写为0
断开连接时间归零
发送数据状态为发送数据完成
网络状态指示灯关
4、接收数据成功中断
复位接收与发送数据超时计数归零
socket0断开连接标识符写为0
断开连接时间归零
发送数据状态为接收数据完成
网络状态指示灯关
5、Socket连接或数据传输超时处理
超时标志位设置为
关闭socket0
网络连接状态为连接失败0
网络状态指示灯亮
在这里插入图片描述
在这里插入图片描述

void W5500_Interrupt_Process(void)
{
    unsigned char i, j;

    i = Read_W5500_1Byte(IR);//读取中断标志寄存器
    Write_W5500_1Byte(IR, (i & 0xf0)); //回写清除中断标志

    if((i & CONFLICT) == CONFLICT)//IP地址冲突异常处理
    {

        IP_Conflict = 1;//30秒后自动复位

    }

    if((i & UNREACH) == UNREACH)//UDP模式下地址无法到达异常处理
    {
        //自己添加代码
        //			SaveEventLog(3, 0, "UDP UNREACH");
    }

    i = Read_W5500_1Byte(SIR); //读取端口中断标志寄存器
    Write_W5500_SOCK_1Byte(0, SIR, i);
    if((i & S0_INT) == S0_INT)//Socket0事件处理
    {
        j = Read_W5500_SOCK_1Byte(0, Sn_IR); //读取Socket0中断标志寄存器
        Write_W5500_SOCK_1Byte(0, Sn_IR, j);
        if((j & IR_CON) == IR_CON) //在TCP模式下,Socket0成功连接
        {
					  Socket0_Connect_Flag = 1;//连接标识
            S0_Con_FailTime = 0;//断开时间归零
            S0_State |= S_CONN; //网络连接状态0x02,端口完成连接,可以正常传输数据
            DBG_LED3_OFF();//网络连接状态指示灯 连接
					  					
            //						DBG_LED4_OFF();//网络连接超时 灭
            //						DEBUG_OUT("Socket0 Success Connect\r\n");
            //断开超时归零
        }
        if((j & IR_DISCON) == IR_DISCON) //在TCP模式下Socket断开连接处理
        {
            Socket0_Disconnect_Flag = 1;//断开连接标识
            Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE); //关闭端口,等待重新打开连接
            Socket_Init(0);		//指定Socket(0~7)初始化,初始化端口0
            S0_State = 0; //网络连接状态0x00,端口连接失败
            DBG_LED3_ON();//网络连接状态指示灯 断开
            //						DEBUG_OUT("Socket0 Disconnect\r\n");
        }
        if((j & IR_SEND_OK) == IR_SEND_OK) //Socket0数据发送完成,可以再次启动S_tx_process()函数发送数据
        {
            Net_Contect = 0;//复位接收与发送数据超时计数
            Socket0_Disconnect_Flag = 0;
            S0_Con_FailTime = 0;//断开时间归零
            S0_Data |= S_TRANSMITOK; //端口发送一个数据包完成
            DBG_LED3_OFF();//W5500发送数据完成指示灯 
            //						DBG_LED4_OFF();//网络连接超时 灭
        }
        if((j & IR_RECV) == IR_RECV) //Socket接收到数据,可以启动S_rx_process()函数
        {
            Net_Contect = 0;//复位接收与发送数据超时计数
           Socket0_Disconnect_Flag = 0;
            S0_Con_FailTime = 0;//断开时间归零
            S0_Data |= S_RECEIVE; //端口接收到一个数据包
            DBG_LED3_OFF();//W5500接收数据完成指示灯
            //						DBG_LED4_OFF();//网络连接超时 灭
        }
        if((j & IR_TIMEOUT) == IR_TIMEOUT) //Socket连接或数据传输超时处理
        {
            Socket0_Timeout_Flag = 1;
            Write_W5500_SOCK_1Byte(0, Sn_CR, CLOSE); // 关闭端口,等待重新打开连接
            S0_State = 0; //网络连接状态0x00,端口连接失败
            DBG_LED3_ON();//网络连接超时 亮
            //						DEBUG_OUT("Socket0 Connect Timeout\r\n");
        }
    }
}

然后判断读取状态读到了就使用吧
if((S0_Data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到数据
S0_Data &= ~S_RECEIVE;//将状态位清零
Read_SOCK_Data_Buffer(0, Rx_Buffer);

先写到这吧后面可能会补充一些网络的知识
参考文件《W5500 数据手册Version 1.0》官网上可以找到

  • 25
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32CubeIDE和HAL库的W5500驱动代码: 首先,在CubeMX中配置GPIO和SPI,然后生成代码。 然后,在main.c文件中初始化W5500并设置其寄存器。 ```c #include "main.h" #include "spi.h" #include "gpio.h" #include "w5500.h" W5500_Dev w5500_dev; int main(void) { HAL_Init(); MX_GPIO_Init(); MX_SPI1_Init(); W5500_Init(&w5500_dev, &hspi1, GPIOA, GPIO_PIN_4); W5500_SetMACAddress(&w5500_dev, (uint8_t *)"AA:BB:CC:DD:EE:FF"); W5500_SetIPAddress(&w5500_dev, 192, 168, 1, 100); W5500_SetGatewayAddress(&w5500_dev, 192, 168, 1, 1); W5500_SetSubnetMask(&w5500_dev, 255, 255, 255, 0); while (1) { // loop } } ``` 在w5500.h头文件中定义了驱动的API函数。 ```c #ifndef __W5500_H #define __W5500_H #ifdef __cplusplus extern "C" { #endif #include "stm32f1xx_hal.h" #define W5500_REGISTER_BLOCK_SIZE 0x400 #define W5500_REGISTER_BLOCK_SIZE_SHIFT 10 typedef struct { SPI_HandleTypeDef *spi; GPIO_TypeDef *cs_port; uint16_t cs_pin; } W5500_Dev; void W5500_Init(W5500_Dev *dev, SPI_HandleTypeDef *spi, GPIO_TypeDef *cs_port, uint16_t cs_pin); void W5500_SetMACAddress(W5500_Dev *dev, uint8_t *mac); void W5500_SetIPAddress(W5500_Dev *dev, uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4); void W5500_SetGatewayAddress(W5500_Dev *dev, uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4); void W5500_SetSubnetMask(W5500_Dev *dev, uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4); #ifdef __cplusplus } #endif #endif /* __W5500_H */ ``` 在w5500.c文件中实现了这些API函数。 ```c #include "w5500.h" #define W5500_SPI_TIMEOUT 1000 #define W5500_REGISTER_MODE 0x0000 #define W5500_REGISTER_GATEWAY_ADDRESS 0x0001 #define W5500_REGISTER_SUBNET_MASK 0x0005 #define W5500_REGISTER_MAC_ADDRESS 0x0009 #define W5500_REGISTER_IP_ADDRESS 0x000F #define W5500_MODE_VALUE 0x01 void W5500_Init(W5500_Dev *dev, SPI_HandleTypeDef *spi, GPIO_TypeDef *cs_port, uint16_t cs_pin) { dev->spi = spi; dev->cs_port = cs_port; dev->cs_pin = cs_pin; HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET); uint8_t tx_data[3] = {0x00, 0x00, W5500_MODE_VALUE}; uint8_t rx_data[3] = {0}; HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(dev->spi, tx_data, rx_data, sizeof(tx_data), W5500_SPI_TIMEOUT); HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET); } void W5500_SetMACAddress(W5500_Dev *dev, uint8_t *mac) { uint8_t tx_data[7] = {0x00, 0x09, mac[0], mac[1], mac[2], mac[3], mac[4]}; HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET); HAL_SPI_Transmit(dev->spi, tx_data, sizeof(tx_data), W5500_SPI_TIMEOUT); HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET); } void W5500_SetIPAddress(W5500_Dev *dev, uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4) { uint8_t tx_data[5] = {0x00, 0x0F, ip1, ip2, ip3, ip4}; HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET); HAL_SPI_Transmit(dev->spi, tx_data, sizeof(tx_data), W5500_SPI_TIMEOUT); HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET); } void W5500_SetGatewayAddress(W5500_Dev *dev, uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4) { uint8_t tx_data[5] = {0x00, 0x01, ip1, ip2, ip3, ip4}; HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET); HAL_SPI_Transmit(dev->spi, tx_data, sizeof(tx_data), W5500_SPI_TIMEOUT); HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET); } void W5500_SetSubnetMask(W5500_Dev *dev, uint8_t ip1, uint8_t ip2, uint8_t ip3, uint8_t ip4) { uint8_t tx_data[5] = {0x00, 0x05, ip1, ip2, ip3, ip4}; HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_RESET); HAL_SPI_Transmit(dev->spi, tx_data, sizeof(tx_data), W5500_SPI_TIMEOUT); HAL_GPIO_WritePin(dev->cs_port, dev->cs_pin, GPIO_PIN_SET); } ``` 这些函数中,主要的操作是通过SPI总线向W5500写入寄存器的值。每个寄存器都有一个地址,可以在W5500的数据手册中找到。 注意,这里只给出了一些基本的初始化函数,还可以写更多的函数来配置其他寄存器。同时,还需要编写其他函数来读取和写入数据包以进行网络通信。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值