当前位置:   article > 正文

STM32+W5500实现以太网通信_stm32以太网通信,2024年最新我总结了24家大厂100份面试题_stm32和w5500

stm32和w5500

STM32系列32位微控制器基于Arm® Cortex®-M处理器,旨在为MCU用户提供新的开发自由度。它包括一系列产品,集高性能、实时功能、数字信号处理、低功耗/低电压操作、连接性等特性于一身,同时还保持了集成度高和易于开发的特点。本例采用STM32作为MCU。

W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加简洁的互联网方案。W5500集成了TCP/IP协议栈,10/100M以太网数据链路层(MAC)以及物理层(PHY)。全硬件实现的TCP/IP协议栈支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及PPPoE协议。W5500内嵌32K字节片上缓存以供以太网包处理,用户可以同时使用8个硬件Socket独立通信。W5500使用了高效的SPI协议支持80MHz速率,解决系统通信瓶颈,更好地实现高速网络通信。

文章目录

概念说明

实现原理

嵌入式程序

底层通用接口

W5500抽象接口

官网例程补充说明


概念说明

  • SPI:Serial Peripheral interface是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。SPI分为主、从两种模式,一个SPI通讯系统需要包含一个(且只能是一个)主设备,一个或多个从设备。这里STM32为主设备(Master)提供时钟,W5500为从设备(Slave)。SPI接口一般使用四条信号线通信:SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)
    • MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。
    • MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
    • SCLK:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
    • CS/SS:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。从设备片选信号,由主设备控制。它的功能是用来作为“片选引脚”,也就是选择指定的从设备,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。
  • TCP/IP协议:TCP/IP协议是Internet互联网最基本的协议,其在一定程度上参考了七层ISO模型。OSI模型共有七层,在TCP/IP协议中,七层被简化为了四个层次。TCP/IP模型中的各种协议,依其功能不同,被分别归属到这四层之中,常被视为是简化过后的七层OSI模型。 W5500实现的部分为红框部分:
  • Socket:在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一个虚拟通道描述符,一个socket对应着网络通信的一扇门。
  • 网络参数:网络通信需要的参数有很多,我这里介绍一下我们常见的:
    • IP地址:Internet Protocol Address是指互联网协议地址,两台通过IP协议通信的机器通过IP地址寻找对方,子网掩码配合IP地址能得到对端IP地址是在本地子网,还是需要发送至网关进行路由发送至广域网。
    • MAC地址:Media Access Control 地址是制造商为网络硬件 (如无线网卡或以太网网卡)分配的唯一代码。MAC地址作为数据链路设备的地址标识符,ARP协议局域网寻址使用MAC地址。
    • 网络端口号:网络中的计算机是通过IP地址来代表其身份的,它只能表示某台特定的计算机,但是一台计算机上可以同时提供很多服务,比如常见的端口号21表示的是FTP服务。端口号是socket的属性之一。
    • DNS/DHCP/网关:网关作为局域网的一个出口可以将报文转发至广域网中,DNS服务器提供域名解析功能,DHCP服务器提供局域网IP地址管理功能。

实现原理

嵌入式程序跑在STM32微控制器,通过片上SPI控制器与W5500进行通信,配置所需网络参数并与远端服务器建立链接(TCP客户端)之后发送接收数据;又或者是建立服务器(TCP服务器)等待建立链接之后收发数据。抑或是不用建立连接直接发送报文(UDP)。PHY信号变压之后通过RJ45接口收发至网线。原理示意图如下:


嵌入式程序

嵌入式程序分两个部分,第一部分是一些底层通用接口。第二部分W5500抽象供上层调用的接口。

底层通用接口

这部分实现主要包括IO口控制器初始化,以及MCU不同位宽配置芯片接口和Socket批量发送接收数据接口,代码片如下(中文注释帮助您更好的理解实现):

//IO口控制器初始化
uint8 w55_IoInit(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef    SPI_InitStructure;
  RCC_APB2PeriphClockCmd(SPI_CS_RCC|SPI_SCLK_RCC|SPI_SO_RCC|SPI_SI_RCC|W5500_RESET_RCC|LINK_RCC|RCC_APB2Periph_AFIO,ENABLE);
  
	/*使能AFIO时钟*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);   
	/*只保留SWD模式*/
  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);   
                    
  RCC_APB1PeriphClockCmd(W5500_SPI_CLK ,ENABLE);
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
  GPIO_InitStructure.GPIO_Pin   = W5500_RESET_pin;
  GPIO_Init(W5500_RESET_GPIO, &GPIO_InitStructure);
                          
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin =SPI_CS_pin;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(SPI_CS_GPIO, &GPIO_InitStructure);
  GPIO_SetBits(SPI_CS_GPIO,SPI_CS_pin);
 
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin =SPI_SCLK_pin|SPI_SI_pin|SPI_SO_pin;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(SPI_SCLK_GPIO, &GPIO_InitStructure);
	GPIO_SetBits(SPI_SCLK_GPIO,SPI_SCLK_pin|SPI_SI_pin|SPI_SO_pin);

  RCC_APB1PeriphClockCmd(LINK_RCC ,ENABLE);
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = LINK_pin;
  GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(LINK_GPIO, &GPIO_InitStructure);
	
	

	SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode=SPI_Mode_Master;									
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;						
	SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;										
	SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;										
	SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;											
	SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;		
	SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;							
	SPI_InitStructure.SPI_CRCPolynomial=7;												
	SPI_Init(W5500_SPI, &SPI_InitStructure); 
	SPI_Cmd(W5500_SPI,ENABLE);
	return 1;
}

//spi发送一个字节
void SPI_Send_Byte(unsigned char dat)
{
	while (SPI_I2S_GetFlagStatus(W5500_SPI, SPI_I2S_FLAG_TXE) == RESET); 
	SPI_I2S_SendData(W5500_SPI, dat);
}
//spi接收一个字节
unsigned char SPI_Recv_Byte(void)
{
	return (uint8)(SPI_I2S_ReceiveData(W5500_SPI));
}
//spi发送两个字节
void SPI_Send_Short(unsigned short dat)
{
	SPI_Send_Byte(dat/256);
	SPI_Send_Byte(dat);	
}
//通过spi向指定地址寄存器写n个字节数据
uint8 w55_WritenByte(uint16 reg, uint8 *dat_ptr, uint16 size)
{
	unsigned short i;

	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);	
		
	SPI_Send_Short(reg);
	SPI_Send_Byte(VDM|RWB_WRITE|COMMON_R);

	for(i=0;i<size;i++)
	{
		SPI_Send_Byte(*dat_ptr++);
	}

	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); 
	
	return 1;
}
//读取W5500指定地址1Byte数据
uint8 w55_Read1Byte(uint16 reg)
{
	unsigned char i;

	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);
			
	SPI_Send_Short(reg);
	SPI_Send_Byte(FDM1|RWB_READ|COMMON_R);
	i=SPI_Recv_Byte();
	
	SPI_Send_Byte(0x00);
	i=SPI_Recv_Byte();

	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);
	return i;
}
///
//华丽的分割线
///
//单字节配置socket
uint8 w55_WriteSock1Byte(SOCKET s, uint16 reg, uint8 dat)
{
	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);
		
	SPI_Send_Short(reg);
	SPI_Send_Byte(FDM1|RWB_WRITE|(s*0x20+0x08));
	SPI_Send_Byte(dat);

	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);
	
	return 1;
}
//两字节配置socket
uint8 w55_WriteSock2Byte(SOCKET s, uint16 reg, uint16 dat)
{
	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);
			
	SPI_Send_Short(reg);
	SPI_Send_Byte(FDM2|RWB_WRITE|(s*0x20+0x08));
	SPI_Send_Short(dat);

	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);
	
	return 1;
}
//四字节配置socket
uint8 w55_WriteSock4Byte(SOCKET s, uint16 reg, uint8 *dat_ptr)
{
	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);//ÖÃW5500µÄSCSΪµÍµçƽ
			
	SPI_Send_Short(reg);
	SPI_Send_Byte(FDM4|RWB_WRITE|(s*0x20+0x08));

	SPI_Send_Byte(*dat_ptr++);
	SPI_Send_Byte(*dat_ptr++);
	SPI_Send_Byte(*dat_ptr++);
	SPI_Send_Byte(*dat_ptr++);

	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS); 
	
	return 1;
}
//读取Socket1字节信息
uint8 w55_ReadSock1Byte(SOCKET s, uint16 reg)
{
	unsigned char i;

	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);
			
	SPI_Send_Short(reg);
	SPI_Send_Byte(FDM1|RWB_READ|(s*0x20+0x08));

	//i=SPI_I2S_ReceiveData(W5500_SPI);
	i=SPI_Recv_Byte();
	SPI_Send_Byte(0x00);
	//i=SPI_I2S_ReceiveData(W5500_SPI);
	i=SPI_Recv_Byte();

	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);
	return i;
}
//读取2字节socket信息
uint16 w55_ReadSock2Byte(SOCKET s, uint16 reg)
{
	unsigned short i;

	GPIO_ResetBits(W5500_SCS_PORT, W5500_SCS);
			
	SPI_Send_Short(reg);
	SPI_Send_Byte(FDM2|RWB_READ|(s*0x20+0x08));

	i=SPI_Recv_Byte();
	SPI_Send_Byte(0x00);
	i=SPI_Recv_Byte();
	SPI_Send_Byte(0x00);
	i*=256;
	i+=SPI_Recv_Byte();
	GPIO_SetBits(W5500_SCS_PORT, W5500_SCS);
	return i;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194

W5500抽象接口

这部分主要实现了芯片以及Socket初始化,模拟中断处理循环函数等,示例使用Socket0实现TCP客户端,您可以在此代码基础上增加配置别的Socket实现TCP服务器以及UDP等。代码片(会有中文注释帮助您更好地理解程序)如下,你会通过这部分代码片体会到C51单片机程序的编程风格(尤其是开始的两个接口):

//从Socket接收数据缓存区读取数据
uint16 w55_ReadSockToBuffer(SOCKET s, uint8 *dat_ptr)
{
    unsigned short rx_size;
	unsigned short offset, offset1;
	unsigned short i;
	unsigned char j;

	rx_size=w55_ReadSock2Byte(s,W5500_Sn_RX_RSR);
	if(rx_size==0) return 0;//没接收到数据则返回
	if(rx_size>S_RX_SIZE) rx_size=S_RX_SIZE;		


**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Linux运维工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/11dea997e2a1a315937c391f5a2d1cdc.png)
![img](https://img-blog.csdnimg.cn/img_convert/4344bb54f52d54bbcc50569674e97d6b.png)
![img](https://img-blog.csdnimg.cn/img_convert/adec74d86c99c8095fbf71a7ee6d0eb6.png)
![img](https://img-blog.csdnimg.cn/img_convert/37ffa78052d040f3a7cdf8641ddd5c5e.png)
![img](https://img-blog.csdnimg.cn/img_convert/0008317c8392afac9dca42dd311afa16.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Linux运维知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加VX:vip1024b (备注Linux运维获取)**
![img](https://img-blog.csdnimg.cn/img_convert/4e09d5104b79a826b4a0b225d4cf7fab.jpeg)



### 最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

### 资料预览

给大家整理的视频资料:

![](https://img-blog.csdnimg.cn/img_convert/a28531ff99a3aea05939f169c4788558.png)

给大家整理的电子书资料:

  

![](https://img-blog.csdnimg.cn/img_convert/d8b92fab65b5a0ea33c82f0a1e8db379.png)



**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**


**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
![img](https://img-blog.csdnimg.cn/img_convert/bcb9e70a3cc5fa01f4b10250b828419a.jpeg)

电子书、PPT等共享给大家!

### 资料预览

给大家整理的视频资料:

[外链图片转存中...(img-PTCR3Umi-1712719197756)]

给大家整理的电子书资料:

  

[外链图片转存中...(img-F1dJfeQn-1712719197756)]



**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**


**一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
[外链图片转存中...(img-6Q4CxyAd-1712719197756)]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/659565
推荐阅读
相关标签
  

闽ICP备14008679号