ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

W5500

2021-07-08 12:59:30  阅读:293  来源: 互联网

标签:HAL SPI4 W5500 SOCK SPI GPIO gWIZNETINFO2


关于使用W5500的介绍

一.关于5500的介绍及使用

相关资料连接: w5500数据手册.

注意
  1. MCU与W5500通讯使用 SPI协议
  2. W5500发送函数int32_t send(uint8_t sn, uint8_t * buf, uint16_t len);
  3. W5500接收数据函int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len);
  4. 本案例用的是STM32H743,同时是使用HAL库进行相关配置。

二.数据手册分析

在这里插入图片描述
上图是接线方式,该芯片内部已经有TCP/IP协议,不需要使用者去移植lwpi,只需要确保SPI通讯没问题即可。

三.代码分析

模块一:
使能初始化SPI

SPI_HandleTypeDef SPI4_Handler;     //SPI4句柄

void SPI4Init()
{
  SPI4_Handler.Instance=SPI4;                      //SP4
  SPI4_Handler.Init.Mode=SPI_MODE_MASTER;          //设置SPI工作模式,设置为主模式
  SPI4_Handler.Init.Direction=SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式
  SPI4_Handler.Init.DataSize=SPI_DATASIZE_8BIT;    //设置SPI的数据大小:SPI发送接收8位帧结构
  SPI4_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //串行同步时钟的空闲状态为高电平
  SPI4_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;      //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
  SPI4_Handler.Init.NSS=SPI_NSS_SOFT;              //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  SPI4_Handler.Init.NSSPMode=SPI_NSS_PULSE_DISABLE;//NSS信号脉冲失能
  SPI4_Handler.Init.MasterKeepIOState=SPI_MASTER_KEEP_IO_STATE_ENABLE;  //SPI主模式IO状态保持使能
	SPI4_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_4;
  SPI4_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;     //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  SPI4_Handler.Init.TIMode=SPI_TIMODE_DISABLE;     //关闭TI模式
  SPI4_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
  SPI4_Handler.Init.CRCPolynomial=0x00;//7;               //CRC值计算的多项式
	HAL_SPI_Init( &SPI4_Handler);//初始化
	__HAL_SPI_ENABLE(&SPI4_Handler);                 //使能SPI4
}



void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
	//SPI4引脚初始化
    if(hspi->Instance==SPI4)
	{
		GPIO_InitTypeDef GPIO_Initure;
		RCC_PeriphCLKInitTypeDef SPI4ClkInit;
	
		__HAL_RCC_SPI4_CLK_ENABLE();
		__HAL_RCC_GPIOE_CLK_ENABLE();
		__HAL_RCC_GPIOI_CLK_ENABLE();
		
     //设置SPI4的时钟源 
		SPI4ClkInit.PeriphClockSelection=RCC_PERIPHCLK_SPI4;	
		SPI4ClkInit.Spi45ClockSelection=RCC_SPI45CLKSOURCE_D2PCLK1;
		if(HAL_OK != HAL_RCCEx_PeriphCLKConfig(&SPI4ClkInit))
		{
		  printf("SPI4 CLK init error!\n");
		}
		
		GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6;
	    GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //复用推挽输出
	    GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
	    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;   //快速    
	    GPIO_Initure.Alternate=GPIO_AF5_SPI4;           //复用为SPI4
	    HAL_GPIO_Init(GPIOE,&GPIO_Initure);             //初始化
			
		/*定义片选引脚*/
		GPIO_Initure.Pin = GPIO_PIN_4;		 
		GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;		
		GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
		HAL_GPIO_Init(GPIOE, &GPIO_Initure);
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET);

		/*定义RESET引脚*/	
		GPIO_Initure.Pin = GPIO_PIN_3; 
		GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
		GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
		HAL_GPIO_Init(GPIOE, &GPIO_Initure);
		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
		
		/*定义INT引脚*///外部中断引脚-无效
		GPIO_Initure.Pin = GPIO_PIN_8;
		GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;	
		GPIO_Initure.Mode = GPIO_MODE_IT_RISING;
		HAL_GPIO_Init(GPIOI, &GPIO_Initure);
		HAL_GPIO_WritePin(GPIOI, GPIO_PIN_8, GPIO_PIN_RESET);
	}
}



//进入临界区
void SPI4_CrisEnter()
{
   // __set_PRIMASK(1);//可用可不用
}
//退出临界区
void SPI4_CrisExit()
{
   // __set_PRIMASK(0);//可用可不用
}

//片选拉低
void SPI4_NSS_Select()
{
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_RESET);
}

//片选拉高
void SPI4_NSS_Deselect()
{
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET);
}

//w5500复位
void w5500_SPI_reset()
{
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_RESET);
  	delay_ms(500);
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
  	delay_ms(500);
}


//从SPI总线读取1字节数据
u8 SPI4_ReadByte(void)
{	
	u8 Rxdata, TxData;
	TxData = 0xFF;
	HAL_SPI_TransmitReceive(&SPI4_Handler, &TxData, &Rxdata, 1, 1000);
	return Rxdata;
}

//写1字节数据到SPI总线
void SPI4_WriteByte(u8 TxData)
{
	u8 Rxdata;
	HAL_SPI_TransmitReceive(&SPI4_Handler, &TxData, &Rxdata, 1, 1000);
}

模块二:
注册W5500函数

//******************************外部网口注册配置初始化******************************//
void ExternalNetworkInit()
{
	uint8_t tmp;
	uint8_t memsize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};//设置接收端和发送端的芯片内部缓冲区大小,一个有8个socket,每个socket的接收端和发送端缓存设置为2(2KB大小);
	do
	{
		SPI4Init();													  //初始化spi
		reg_wizchip_cris_cbfunc(SPI4_CrisEnter, SPI4_CrisExit);	  //注册临界区函数
		reg_wizchip_cs_cbfunc(SPI4_NSS_Select, SPI4_NSS_Deselect); //注册SPI片选信号函数
		reg_wizchip_spi_cbfunc(SPI4_ReadByte, SPI4_WriteByte);	  //注册读写函数

		w5500_SPI_reset();
		/* WIZCHIP SOCKET Buffer initialize */
		if (ctlwizchip(CW_INIT_WIZCHIP, (void *)memsize) == -1)
		{
			printf("WIZCHIP Initialized fail.\r\n");
		}
		/* PHY link status check */
		do
		{
			if (ctlwizchip(CW_GET_PHYLINK, (void *)&tmp) == -1)
			{
				printf("Unknown PHY Link stauts.\r\n");
			}
			if (tmp == PHY_LINK_OFF)
			{
				printf("PHY Link off\n");
			}
		} while (0); //tmp == PHY_LINK_OFF);

		//设置和读取网络配置
		ctlnetwork(CN_SET_NETINFO, (void *)&gWIZNETINFO2);
		ctlnetwork(CN_GET_NETINFO, (void *)&gWIZNETINFO_temp);
	}

	while (memcmp((const char *)&gWIZNETINFO2, (char *)&gWIZNETINFO_temp, sizeof(gWIZNETINFO2)) != 0);//因为可能会初始化失败,所以在初始化后重新把寄存器的配置参数读出来进行比较,判断初始化W5500是否成功!!!
	// Display Network Information
	//	ctlwizchip(1,CW_GET_ID,(void*)tmpstr);//获取芯片ID
	//	printf("\r\n=== %s NET CONF ===\r\n",(char*)tmpstr);
	//	printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",gWIZNETINFO2.mac[0],gWIZNETINFO2.mac[1],gWIZNETINFO2.mac[2],gWIZNETINFO2.mac[3],gWIZNETINFO2.mac[4],gWIZNETINFO2.mac[5]);
	//	printf("SIP: %d.%d.%d.%d\r\n", gWIZNETINFO2.ip[0],gWIZNETINFO2.ip[1],gWIZNETINFO2.ip[2],gWIZNETINFO2.ip[3]);
	//	printf("GAR: %d.%d.%d.%d\r\n", gWIZNETINFO2.gw[0],gWIZNETINFO2.gw[1],gWIZNETINFO2.gw[2],gWIZNETINFO2.gw[3]);
	//	printf("SUB: %d.%d.%d.%d\r\n", gWIZNETINFO2.sn[0],gWIZNETINFO2.sn[1],gWIZNETINFO2.sn[2],gWIZNETINFO2.sn[3]);
	//	printf("DNS: %d.%d.%d.%d\r\n", gWIZNETINFO2.dns[0],gWIZNETINFO2.dns[1],gWIZNETINFO2.dns[2],gWIZNETINFO2.dns[3]);
	//printf("Port: %d\r\n",network.port);
	//printf("======================\r\n");
	
	printf("finish restart network\n");
}

模块三:
W5500轮询检测


#define SOCK_TCPS_Server             0 //通道0-7都可以用
//W5500作为服务端的轮询:
u32 local_port=8080;//设置该通道的port端口号
void do_tcp_server(void)
{	
	uint16 len=0;
	W5500_Use_Flag = 1;
	switch(getSn_SR(SOCK_TCPS_Server))		/*获取socket的状态*/
	{
		case SOCK_CLOSED:	/*socket处于关闭状态*/
		     socket(SOCK_TCPS_Server,Sn_MR_TCP,local_port,Sn_MR_ND);/*打开socket*/
		     break;     
		case SOCK_INIT:	/*socket已初始化状态*/
			 printf("处于监听状态\r\n");
			 listen(SOCK_TCPS_Server);	/*socket建立监听*/	
             break;
		case SOCK_ESTABLISHED:	/*socket处于连接建立状态*/
			 printf("处于建立连接状态\r\n");
			 if(getSn_IR(SOCK_TCPS_Server) & Sn_IR_CON)
			 {
			 	setSn_IR(SOCK_TCPS_Server, Sn_IR_CON);	/*清除接收中断标志位*/
			 }
			 len=getSn_RX_RSR(SOCK_TCPS_Server);/*定义len为已接收数据的长度*/
			 if(len>0)
			 {
				recv(SOCK_TCPS_Server,buff,len);/*接收来自Client的数据*/
				buff[len]=0x00; /*添加字符串结束符*/
				printf("%s\r\n",buff);
				send(SOCK_TCPS_Server,buff,len);	/*向Client发送数据*/
		     }
		     break;
	   case SOCK_CLOSE_WAIT:/*socket处于等待关闭状态*/
			close(SOCK_TCPS_Server);
		    break;
	}
}

#define SOCK_TCPS_Client             1 //通道0-7都可以用
//W5500作为客户端的轮询:

void do_tcp_client(void)
{	
    uint16 len=0;	
	switch(getSn_SR(SOCK_TCPS_Client))		/*获取socket的状态*/
	{
		case SOCK_CLOSED:	/*socket处于关闭状态*/
			socket(SOCK_TCPS_Client,Sn_MR_TCP,local_port++,Sn_MR_ND);
			break;
		case SOCK_INIT:		/*socket处于初始化状态*/
			connect(SOCK_TCPS_Client,serverip,serverport);   /*socket连接服务器*/ 
			//serverip为服务器的IP,serverport服务器的端口号
		    break;
	   case SOCK_ESTABLISHED:  /*socket处于连接建立状态*/
			if(getSn_IR(SOCK_TCPS_Client) & Sn_IR_CON)
			{
				setSn_IR(SOCK_TCPS_Client, Sn_IR_CON);  /*清除接收中断标志位*/
			}
			len=getSn_RX_RSR(SOCK_TCPS_Client); 	/*定义len为已接收数据的长度*/
			if(len>0)
			{
				recv(SOCK_TCPS_Client,buff,len);  /*接收来自Server的数据*/
				buff[len]=0x00;   /*添加字符串结束符*/
				printf("%s\r\n",buff);
				send(SOCK_TCPS_Client,buff,len);	/*向Server发送数据*/
			}		  
		    break;
		case SOCK_CLOSE_WAIT: 	/*socket处于等待关闭状态*/
			close(SOCK_TCPS_Client);
		    break;
	}
}


注意点:

W5500一共提供8个socket(通道),分别为0-7。
在TCP/IP模式下,每个socket工作时候只能客户端或者服务端,不能同时使用。

标签:HAL,SPI4,W5500,SOCK,SPI,GPIO,gWIZNETINFO2
来源: https://blog.csdn.net/Alex_mx/article/details/118245277

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有