w5500就是一个以太网模块,这个模块本身集成了tcp/ip协议,mcu只需要通过spi协议读写他的寄存器就可以进行数据交互了,

下面大致说说stm32移植w5500的过程和步骤吧,


10个引脚中,真正使用的也就只有vcc gnd miso mosi sclk scs 这几个脚,RST和int引脚如果是引用官方的库的话,是不需要的(RST是复位引脚,INT是中断触发引脚)

移植W5500大致分为下面的几个步骤

  1. 初始化SPI引脚
  2. 初始化SCS引脚(片选)
  3. 下载官方库文件 http://pan.baidu.com/s/1c2EgExq
  4. 添加官方库到工程目录
  5. 实现SPI接口和库文件的对接
  6. 调用官方库提供的函数实现连接

1,初始化SPI
因为W5500模块内部自己实现了TCP/IP协议,所以我们在外部只需要通过他提供的接口把相关的参数传递进去就行了,比如物理地址,本机IP,本机端口,目标端口,目标IP等等,
而模块提供的是一个SPI的数据接口
下面是103的SPI初始化代码

//ÒÔÏÂÊÇSPIÄ£¿éµÄ³õʼ»¯´úÂ룬ÅäÖóÉÖ÷»úģʽ£¬·ÃÎÊSD Card/W25Q64/NRF24L01
//SPI¿Ú³õʼ»¯
//ÕâÀïÕëÊǶÔSPI1µÄ³õʼ»¯
void SPI1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef  SPI_InitStructure;//  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTBʱÖÓʹÄÜ
//  RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1,  ENABLE );//SPI2ʱÖÓʹÄÜ   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15¸´ÓÃÍÆÍìÊä³ö GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOBGPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);  //PB13/14/15ÉÏÀ­SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //ÉèÖÃSPIµ¥Ïò»òÕßË«ÏòµÄÊý¾Ýģʽ:SPIÉèÖÃΪ˫ÏßË«ÏòÈ«Ë«¹¤SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       //ÉèÖÃSPI¹¤×÷ģʽ:ÉèÖÃΪÖ÷SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;   //ÉèÖÃSPIµÄÊý¾Ý´óС:SPI·¢ËͽÓÊÕ8λ֡½á¹¹
//  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;          //ʱÖÓÐü¿ÕµÍ
//  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        //Êý¾Ý²¶»ñÓÚµÚ1¸öʱÖÓÑØSPI_InitStructure.SPI_CPOL = SPI_CPOL_High;     //´®ÐÐͬ²½Ê±ÖӵĿÕÏÐ״̬Ϊ¸ßµçƽSPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //´®ÐÐͬ²½Ê±Öӵĵڶþ¸öÌø±äÑØ£¨ÉÏÉý»òϽµ£©Êý¾Ý±»²ÉÑùSPI_InitStructure.SPI_NSS = SPI_NSS_Soft;           //NSSÐźÅÓÉÓ²¼þ£¨NSS¹Ü½Å£©»¹ÊÇÈí¼þ£¨Ê¹ÓÃSSI룩¹ÜÀí:ÄÚ²¿NSSÐźÅÓÐSSIλ¿ØÖÆSPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//²¨ÌØÂÊÔ¤·ÖƵֵ:²¨ÌØÂÊÔ¤·ÖƵֵΪ256 ³õʼ»¯Ê±Îª×îµÍËÙģʽSPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  //Ö¸¶¨Êý¾Ý´«Êä´ÓMSBλ»¹ÊÇLSBλ¿ªÊ¼:Êý¾Ý´«Êä´ÓMSBλ¿ªÊ¼SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRCÖµ¼ÆËãµÄ¶àÏîʽSPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); //ʹÄÜSPIÍâÉè//  SPI1_ReadWriteByte(0xff);//Æô¶¯´«Êä      }
//SPI ËÙ¶ÈÉèÖú¯Êý
//SpeedSet:
//SPI_BaudRatePrescaler_2   2·ÖƵ
//SPI_BaudRatePrescaler_8   8·ÖƵ
//SPI_BaudRatePrescaler_16  16·ÖƵ
//SPI_BaudRatePrescaler_256 256·ÖƵ void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));SPI1->CR1&=0XFFC7;SPI1->CR1|=SPI_BaudRatePrescaler;   //ÉèÖÃSPIËÙ¶È SPI_Cmd(SPI1,ENABLE); } 

2,初始化GPIO
除去SPI口之外还有一个片选引脚SCS,这个引脚很重要,在官方协议实现的4个函数中,起到的很关键的作用,我的开发板上这个引脚是放到了PA0上,下面是初始化代码

void W5500_GPIO_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );// ???????SPI-CS?? (PA0)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_0);
}

3,下载官方库代码,
官方库代码分为三个部分

  1. 基本的SOCKET连接和部分头文件
  2. DHCP协议的文件(用来自动获取本地IP的协议)
  3. DNS协议文件(用来解析域名的)

我上面提供的百度网盘中包括1,2,3和帮助文档CHM
如果只需要实现基本的tcp,udp协议只需要移植1就可以了,如果想要DHCP来自动获取本地IP,就需要把DHCP添加进去,如果要实现域名解析就需要DNS协议,也已实现部分也可以全部实现,下面会讲解具体的实现步骤和函数用法
socket.c 文件夹里面主要是socket的一些函数,比如close connect socket等等函数,实现了一些应用层的封装
w5500.c 文件主要实现的是对W5500模块寄存器的读写和操作,包括读写那些寄存器,地址是多少等等,
wizchip_conf.c 就是一个公共文件主要包括和SPI的连接以及连接W5500读写寄存器函数和socket函数。
DHCP.c 主要就是初始化DHCP,启动DHCP,获取ip,端口等函数
DNS.c 主要也就是一个初始化函数,一个获取函数,还有一个hande函数
以上的具体使用下面再说

4,添加文件到工程
这个比较简单,如果是使用的keil,直接把文件添加进去,然后c/c++ 下面的include path添加相应的目录就可以了

5,实现SPI和库文件对接
前面说了库文件wizchip_conf.c 里面就包括了和SPI口的对接实现函数,其实也就是一个函数指针,
在spi里实现一些函数,然后把函数名赋值给wizchip_conf.c里面的一些函数指针,这样W5500.c里面的函数实现读写的时候,就能够直接使用SPI接口了,
具体实现的函数有以下6个

void SPI1_WriteByte(u8 TxData)
u8 SPI1_ReadByte()
void SPI_CrisEnter(void)
void SPI_CrisExit(void)
void SPI_CS_Select(void)
void SPI_CS_Deselect(void)

函数名可以自己随便改,这个不重要

实现了这几个函数之后,需要把他们注册到库函数里面(也就是把函数指针赋值给别人调用)

官方提供了一串代码

void register_wizchip()
{// First of all, Should register SPI callback functions implemented by user for accessing WIZCHIP /* Critical section callback */reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);   /* Chip selection call back */reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);/* SPI Read & Write callback function */reg_wizchip_spi_cbfunc(SPI1_ReadByte, SPI1_WriteByte);
}

这个函数是我自己包含的,官方提供的代码里面还包含一些宏定义,不过被我干掉了

在初始化函数调用这个函数之后,就把SPI接口的函数传递给库了,这样库在调用读写的时候,就能够正常读写了

下面是上面 几个函数的实现代码

//SPIx ¶Áдһ¸ö×Ö½Ú
//TxData:ҪдÈëµÄ×Ö½Ú
//·µ»ØÖµ:¶ÁÈ¡µ½µÄ×Ö½Ú
void SPI1_WriteByte(u8 TxData)
{       while((SPI1->SR&SPI_I2S_FLAG_TXE)==0);   //??????          SPI1->DR=TxData;                                         //????byte while((SPI1->SR&SPI_I2S_FLAG_RXNE)==0); //???????byte  SPI1->DR;
}u8 SPI1_ReadByte()
{while((SPI1->SR&SPI_I2S_FLAG_TXE)==0);   //??????              SPI1->DR=0xFF;                                               //???????????????? while((SPI1->SR&SPI_I2S_FLAG_RXNE)==0); //???????byte  return SPI1->DR;
}/*** @brief  ?????* @retval None*/
void SPI_CrisEnter(void)
{__set_PRIMASK(1);
}
/*** @brief  ?????* @retval None*/
void SPI_CrisExit(void)
{__set_PRIMASK(0);
}/*** @brief  ?????????* @retval None*/
void SPI_CS_Select(void)
{GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
/*** @brief  ?????????* @retval None*/
void SPI_CS_Deselect(void)
{GPIO_SetBits(GPIOA,GPIO_Pin_0);
}

PS,这里说一下,SPI的读写函数,有很多种写法,但是我测试过后发现,就这种是好的,具体原因不晓得,可能和库函数读写的时序有关,其他的的读写方式单独使用的时候都是好的,但是添加到库里面就不行了
PPS,上面的GPIO_0 就是上面说的SCS接口,按照自己开发板写就好了

6,调用函数接口实现TCP客户端的实现

官方提供了3个函数,分别是建立tcp,UDP,和tcp server,如果不移植DHCP协议,用户只需要填写本机IP地址和目标IP地址和目标端口以及,选择0~7的其中一条链路

三个具体的函数我就不放了,放一个github的连接把
https://github.com/wxcIIdogs/ioLibrary_Driver/tree/master/Application/loopback

以建立一个TCP客户端为例子说明一下函数调用的流程

  1. wiz_NetInfo gWIZNETINFO; 初始化这个变量,其中包括IP,MAC等等数据
  2. ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO); 调用这个函数和这个参数把数据写入到W5500的寄存器
  3. int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport) 调用这个函数,并且实现部分数据,比如端口,比如IP地址
  4. 在swtich语句的下面找到SOCK_ESTABLISHED这个的下面,在这个选项的下面包括数据的读取和发送,函数名称分别是recv和send

使用了loopback_tcpc函数之后,tcp的连接完全不用我们管,因为他会读取W5500的寄存器自己再连接,

下面是DHCP的实现方向
1,添加DHCP文件到工程
这个貌似没啥好说的
2,对DHCP进行初始化代码如下

        uint8_t memsize[2][8] = { {2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};if(ctlwizchip(0,(void*)memsize) == -1){printf("WIZCHIP Initialized fail.\r\n");while(1);}setSHAR(gWIZNETINFO.mac);DHCP_init(0,buff);reg_dhcp_cbfunc(my_ip_assign, my_ip_assign, my_ip_conflict);uint8_t dhcp_ret = DHCP_run();while(dhcp_ret != DHCP_IP_LEASED){delay_ms(500);dhcp_ret = DHCP_run();}

第一步是初始化ctlwizchip函数,
第二部是设置mac地址,可以放到别的地方或者改变顺序,
第三部是初始化DHCP,buff就是一个数组
第三部是初始化reg_dhcp_cbfunc函数,他实现的两个函数分别是

void my_ip_assign(void)
{getIPfromDHCP(gWIZNETINFO.ip);getGWfromDHCP(gWIZNETINFO.gw);getSNfromDHCP(gWIZNETINFO.sn);getDNSfromDHCP(gWIZNETINFO.dns);gWIZNETINFO.dhcp = NETINFO_DHCP;/* Network initialization */network_init();      // apply from dhcp //这是我自己实现的,内部的实现函数就是
//   ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);   printf("DHCP LEASED TIME : %d Sec.\r\n", getDHCPLeasetime());
}
void my_ip_conflict(void)
{printf("CONFLICT IP from DHCP\r\n");//halt or reset or any...while(1); // this example is halt.
}

第四部就是运行run函数,并且等待ip地址获取成功,也就是返回码等待4,DHCP_IP_LEASED,在一个贴吧里面看到有个哥们给的代码是success,不知道为啥,我下载的库里面没有和这个枚举,测试了很久发现是等于4的时候是正常的之后就可以在mian里面进行读写处理了,

DNS其实很简单,就两个函数,一个是DNS_init初始化,一个是int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
这个函数的三个参数,文档上也有写

/*
* @brief DNS process
* @details Send DNS query and receive DNS response
* @param dns_ip : DNS server ip
* @param name : Domain name to be queryed
* @param ip_from_dns : IP address from DNS server
* @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n
* 0 : failed (Timeout or Parse error)\n
* 1 : success
* @note This funtion blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
*/

返回1是代表成功了,
dns_ip是dns服务器的ip地址,这个随便百度一个就可以了
name是我们需要解析的域名,比如www.baidu.com
ip_from_dns是返回的指针数据,也就是www.baidu.com的ip地址

DNS最典型的运用是PC的时候的ping

如果没有DNS的话是没有办法直接连接百度的服务器的,只有通过DNS服务器解析之后,获取到百度的IP之后,才能正常的使用
下面是我百度到的几个DNS服务器ip地址,

       OneDNS  (112.124.47.27)OpenerDNS(42.120.21.30)BaiduDNS (180.76.76.76)aliDNS (223.5.5.5, 223.6.6.6)114DNS (114.114.114.114, 114.114.115.115)114DNS安全版 (114.114.114.119, 114.114.115.119)114DNS家庭版 (114.114.114.110, 114.114.115.110)Dns派:电信/移动/铁通 (101.226.4.6, 218.30.118.6)Dns派:联通 (123.125.81.6, 140.2
07.198.6)

好久没写,算是做个开始把

stm32-W5500-官网教程相关推荐

  1. [pytorch] 官网教程+注释

    pytorch官网教程+注释 Classifier import torch import torchvision import torchvision.transforms as transform ...

  2. MNE溯源fieldtrip官网教程

    MNE溯源fieldtrip官网教程 Introduction 在本教程中,您可以找到有关如何使用最小范数估计进行源重构的信息,以重构单个主题的事件相关字段(MEG).我们将使用预处理教程中描述的数据 ...

  3. Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习

    Spring Cloud学习笔记-网关Spring Cloud Gateway官网教程实操练习 1.Spring Cloud Gateway介绍 2.在Spring Tool Suite4或者IDEA ...

  4. Gem5模拟器,详解官网教程Event-driven programming(五)

    目录 一.解释一下gem5中的event-driven? 二.Creating a simple event callback (1)定义一个新的 C++ 类,并继承自 SimObject 抽象基类 ...

  5. java官网教程(基础篇)—— 基础的Java类 —— 基础 I / O

    目录 基本 Java 类 基础 I/O I/O流 字节流 字符流 缓冲流 扫描和格式化 扫描 格式化 从命令行中进行IO操作 数据流 对象流 文件 I/O(采用 NIO.2) 什么是路径? Path类 ...

  6. Angular官网教程示例知识点总结

    Angular官网教程示例知识点总结 1.背景 2.知识点 2.1 应用的外壳 2.1.1 使用 Angular CLI 创建初始的应用结构 2.1.2 启动应用服务器 2.1.3 双花括号表达式 2 ...

  7. Docker 官网教程实践 自定义 bridge 网络

    前言 这篇笔记是 docker 官网教程 自定义 bridge 网络的实践. 用户自定义 bridge 网络是在生产环境中推荐到最佳方式,因此这篇教程要特别注意. 这个教程中,启动了2个 alpine ...

  8. Away3D 4.0官网教程(翻译)

    使用Away3D 4.Stage3D 创建3D游戏和应用程序 (此帖每天都会更新,一定让大家完全的搞明白) 补充区:        'vase.awd' 可以使用 Prefab3D打开(在帖子后面回复 ...

  9. CMake学习笔记(一)——CMake官网教程

    CMake学习笔记(一)--CMake官网教程 前言: 经历了一星期痛苦的交叉编译,笔者深刻认知到Linux下make的重要性.所以准备放缓两三天自己的工作进度,并学习一下CMake与Makefile ...

  10. 新学Python之学习官网教程序言

      大家好,我是 herosunly.985 院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用.曾获得阿里云天池安全恶意程序检测第一名,科大讯飞恶意软件分类挑战赛第三名,CCF 恶意软 ...

最新文章

  1. Java中的多态(for myself)
  2. Winform-DataGridView
  3. [转]jQuery源码分析系列
  4. 讲师两年升“教授”,成功实现“三连跳”
  5. nui UI 具有右键属性的菜单树
  6. Kaldi语音识别库linux环境下的安装和编译
  7. 删数问题(Noip1994)--贪心
  8. web-4. 装饰页面的图像
  9. php+mysql事务处理例子详细分析实例
  10. 图解机器学习算法(2) | 模型评估方法与准则(机器学习通关指南·完结)
  11. 基于无线传输的多点温度采集系统
  12. java 多线程 超时_【Java】Java多线程任务超时结束的5种实现方法
  13. access突然需要登录_登录信息提示
  14. Android Launcher启动流程
  15. 新鲜的蔬菜和水果中富含抗氧化物,可以有效延缓衰老和疾病
  16. EXCEPTION_ACCESS_VIOLATION
  17. 边缘设备、系统及计算杂谈(9)——dapr学习之二
  18. Java语言最新实用案例教程_Java语言最新实用案例教程
  19. java生成电子印章的方法
  20. 2020年的第二周 | 关于赚钱 ——《副业赚钱》、基金定投

热门文章

  1. 计算机显示器怎么调左右,电脑屏幕内容左右看不到边怎么调
  2. unparseable date:‘’
  3. 开源项目ruoyi-springboot-vue源码分析之LogAspect日志打印
  4. SpringBoot整合使用XXL-JOB
  5. 复习笔记1-java基础
  6. [原创]IBM BLM模型思维导图
  7. xposed新版52下载_kyqp游戏合集-kyqp游戏下载推荐
  8. 火车票能不能选座_12306可以选座位吗 12306怎么选座位方法介绍
  9. Scrapy crawl 爬虫运行出错解决方法
  10. centos安装unrar并使用