赞
踩
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速率,解决系统通信瓶颈,更好地实现高速网络通信。
文章目录
嵌入式程序跑在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; }
这部分主要实现了芯片以及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)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。