W5500 芯片是一款集成全硬件 TCP/IP 协议栈的嵌入式以太网控制器,同时也是一颗工业级以太网控制芯片。

W5500 支持高速标准4线SPI接口与主机进行通信,该 SPI 速率理论上可以达到 80MHz。其内部还集成了以太网数据链路层(MAC)和10BaseT/100BaseTX 以太网物理层(PHY),支持自动协商(10/100-Based全双工/半双工)、掉电模式和网络唤醒功能。与传统软件协议栈不同,W5500内嵌的8个独立硬件 Socket 可以进行8路独立通信,该8路Socket的通信效率互不影响,可以通过 W5500 片上32K 字节的收/发缓存灵活定义各个Socket的大小

官方提供了ioLibrary_BSD固件库,可以很轻松的移植进各种嵌入式设备中,只要设备支持标准SPI接口(模式0、3)即可。

下面以STM32F103的MCU为例说明一下如何用W5500移植官方的固件库实现以太网通讯。

1、下载官方固件库

地址:
http://wizwiki.net/wiki/doku.php?id=products:w5500:driver

可以分别从官网和github上下载源码。

下载完注意两个部分:

(1)Ethernet文件夹
主要是W5500的驱动,实现基本的TCP通讯只要这个就行了

(2)Internet文件夹
实现各种TCP扩展的应用,比如DHCP、DNS、FTP等

先实现基本的TCP通讯,只要Ethernet文件夹下的文件


将W5500、socket、wizchip_config的c和h文件引入工程中即可(注意配置.h文件路径)

2、编写SPI接口

要写一下MCU的spi接口初始化,同时实现几个函数:

//SPI口初始化
void SPI2_Init(void)
{SPI_InitTypeDef  SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//PB12->CS,PB13->SCK,PB14->MISO,PB15->MOSI    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);//初始化片选输出引脚GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_12);SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;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_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI2,&SPI_InitStructure);SPI_Cmd(SPI2, ENABLE); //使能SPI外设
}/*** @brief  写1字节数据到SPI总线* @param  TxData 写到总线的数据* @retval None*/
void SPI_WriteByte(uint8_t TxData)
{while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);   SPI_I2S_SendData(SPI2, TxData);while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);  SPI_I2S_ReceiveData(SPI2);
}/*** @brief  从SPI总线读取1字节数据* @retval 读到的数据*/
uint8_t SPI_ReadByte(void)
{while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);   SPI_I2S_SendData(SPI2, 0xFF);while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);  return (SPI_I2S_ReceiveData(SPI2));
}/*** @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(GPIOB,GPIO_Pin_12);
}/*** @brief  片选信号输出高电平* @retval None*/
void SPI_CS_Deselect(void)
{GPIO_SetBits(GPIOB,GPIO_Pin_12);
}

(1)SPI读写
(2)进入、退出临界区
(3)片选信号输出

3、初始化W5500

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "spi.h"
#include "socket.h"   // Just include one header for WIZCHIP#define SOCK_TCPC        0
#define SOCK_TCPS        1#define DATA_BUF_SIZE   2048// Initialize Network information and display it
void network_init(void);
// Loopback TCP server
int32_t loopback_tcps(uint8_t, uint8_t*, uint16_t);uint8_t gDATABUF[DATA_BUF_SIZE];wiz_NetInfo gWIZNETINFO = { .mac = {0x00, 0x08, 0xdc,0x00, 0xab, 0xcd},.ip = {10, 1, 1, 200},.sn = {255,255,255,0},.gw = {10, 1, 1, 1},.dns = {8,8,8,8},.dhcp = NETINFO_STATIC};int main(void)
{delay_init();              //延时函数初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2uart_init(115200);     //串口初始化SPI2_Init();    //SPI初始化// 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); //注册临界区函数reg_wizchip_cris_cbfunc(NULL, NULL); // 注册临界区函数reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);// 注册片选函数/* SPI Read & Write callback function */reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte); //注册读写函数/* WIZCHIP SOCKET Buffer initialize */if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1){printf("WIZCHIP Initialized fail.\r\n");while(1);}/* PHY link status check */do{if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1){printf("Unknown PHY Link stauts.\r\n");}}while(tmp == PHY_LINK_OFF);/* Network initialization */network_init();while(1){/* Loopback Test */// TCP server loopback testif( (ret = loopback_tcps(SOCK_TCPS, gDATABUF, 5000)) < 0) {printf("SOCKET ERROR : %ld\r\n", ret);}
}
}//网络初始化(DHCP)
void network_init(void)
{uint8_t tmpstr[6] = {0,};wiz_NetInfo netinfo;// Set Network information from netinfo structurectlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);// Get Network informationctlnetwork(CN_GET_NETINFO, (void*)&netinfo);// Display Network Informationctlwizchip(CW_GET_ID,(void*)tmpstr);if(netinfo.dhcp == NETINFO_DHCP) printf("\r\n=== %s NET CONF : DHCP ===\r\n",(char*)tmpstr);else printf("\r\n=== %s NET CONF : Static ===\r\n",(char*)tmpstr);printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",netinfo.mac[0],netinfo.mac[1],netinfo.mac[2],netinfo.mac[3],netinfo.mac[4],netinfo.mac[5]);printf("SIP: %d.%d.%d.%d\r\n", netinfo.ip[0],netinfo.ip[1],netinfo.ip[2],netinfo.ip[3]);printf("GAR: %d.%d.%d.%d\r\n", netinfo.gw[0],netinfo.gw[1],netinfo.gw[2],netinfo.gw[3]);printf("SUB: %d.%d.%d.%d\r\n", netinfo.sn[0],netinfo.sn[1],netinfo.sn[2],netinfo.sn[3]);printf("DNS: %d.%d.%d.%d\r\n", netinfo.dns[0],netinfo.dns[1],netinfo.dns[2],netinfo.dns[3]);printf("===========================\r\n");}/*** @brief  Loopback Test Example Code using ioLibrary_BSD   * @retval None*/
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{int32_t ret;uint16_t size = 0, sentsize=0;switch(getSn_SR(sn)){case SOCK_ESTABLISHED :if(getSn_IR(sn) & Sn_IR_CON){printf("%d:Connected\r\n",sn);setSn_IR(sn,Sn_IR_CON);}if((size = getSn_RX_RSR(sn)) > 0){if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;ret = recv(sn,buf,size);if(ret <= 0) return ret;sentsize = 0;while(size != sentsize){ret = send(sn,buf+sentsize,size-sentsize);printf("%s\r\n",buf);if(ret < 0){close(sn);return ret;}sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.}}break;case SOCK_CLOSE_WAIT :printf("%d:CloseWait\r\n",sn);if((ret=disconnect(sn)) != SOCK_OK) return ret;printf("%d:Closed\r\n",sn);break;case SOCK_INIT :printf("%d:Listen, port [%d]\r\n",sn, port);if( (ret = listen(sn)) != SOCK_OK) return ret;break;case SOCK_CLOSED:printf("%d:LBTStart\r\n",sn);if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)return ret;printf("%d:Opened\r\n",sn);break;default:break;}return 1;
}

4、检验结果

到此,设备已经实现了TCP服务器通讯,下面需要检验一下:
(1)将设备的网口和电脑的网口用网线连接
(2)暂时关闭电脑的DHCP,更改电脑的本地网络的IPv4地址为固定值,改成和程序中处于同一个网段(或者把程序中的IP地址改成和电脑的同一个网段)

wiz_NetInfo gWIZNETINFO = { .mac = {0x00, 0x08, 0xdc,0x00, 0xab, 0xcd},.ip = {10, 1, 1, 200},.sn = {255,255,255,0},.gw = {10, 1, 1, 1},.dns = {8,8,8,8},.dhcp = NETINFO_STATIC};

比如上文程序中的IP地址为10.1.1.200,则电脑的IP保持前3段不变,如设成10.1.1.199

(3)电脑打开一个网络调试助手,配置好连接参数,然后连接上文程序中指定的地址

(4)发送数据



电脑客户端发送数据,W5500创建的服务器端会将数据按原样返回,同时串口会打印数据。

(5)验证完成,实现W5500的TCP回环测试(TCP服务器功能)

W5500相关文章专栏链接

下一篇文章:

W5500以太网控制器芯片(二):ioLibrary库实现TCP客户端

W5500以太网控制器芯片(一):ioLibrary库实现TCP服务器相关推荐

  1. W5500以太网控制器芯片(三):实现DHCP服务

    #W5500以太网控制芯片相关文章链接# 上一篇文章: W5500以太网控制器芯片(二):ioLibrary库实现TCP客户端 如果要W5500的IP动态分配,则要实现DHCP功能,实现流程如下: 准 ...

  2. W5500以太网控制器芯片(四):实现DNS功能

    #W5500以太网控制芯片相关文章链接# 上一篇: W5500以太网控制器芯片(三):实现DHCP服务 使用W5500时,如果要连接的是域名,则连接TCP服务器前将要域名转成IP再进行连接,这时候就要 ...

  3. Wiznet W5500以太网控制器应用笔记

    引用数据手册的芯片介绍:"W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案.W5500 集成了TCP/IP 协议栈,10/100M 以太 ...

  4. boost asio 文件服务器,使用boost ASIO库封装TCP服务器类

    使用异步TCP方式,可在此基础上增加更多功能. 头文件AsioTcp.h: #pragma once #include #include #include typedef boost::asio::i ...

  5. 通讯接口应用笔记3:使用W5500实现Modbus TCP服务器

      前面我们设计实现了W5500的驱动程序,也讲解了驱动的使用方式.在最近一次的项目应用中,正好有一个使用W5500实现TCP通讯的需求,所以我们就使用该驱动程序轻松实现.这一篇中我们就来说一说基于我 ...

  6. RT-Thread 之 WIZnet 软件包(全硬件TCP/IP协议栈W5500以太网芯片) 以太网 Socket 通信

    目录 1.介绍 1.1 WIZnet 1.2 W5500 2.RT-Thread Studio 配置及相关代码 2.1 添加WIZnet软件包 2.2 配置 WIZnet 软件包 2.3 配置 spi ...

  7. W5500全硬件 TCP/IP 嵌入式以太网控制器WIZNET

    概述 W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案. W5500 集成了 TCP/IP 协议栈,10/100M 以太网数据链路层(MAC)及物 ...

  8. LPC1768以太网控制器

    LPC1768以太网控制器 2012-12-18 17:16:54 分类: 嵌入式 LPC1768以太网控制器 本文记录LPC1768的以太网控制器学习使用心得.网卡芯片以DP83848C为例.主芯片 ...

  9. STM32 W5500以太网通讯

    STM32 W5500以太网通讯 对于内含以太网MAC部分的芯片,可以外部增加以太网PHY芯片和连接器,实现以太网通讯.对于内部没有以太网MAC部分的芯片,通过W5500 SPI转Ethernet芯片 ...

  10. 基于FPGA的以太网控制器(MAC)设计(中)

    今天给大侠带来基于FPGA的以太网控制器(MAC)设计,由于篇幅较长,分三篇.今天带来第二篇,中篇,以太网控制器(MAC)程序的实现.话不多说,上货. 导读 当前,互联网已经极大地改变了我们的生产和生 ...

最新文章

  1. 写单元测试应该注意什么
  2. 5款非常好用的前端在线编辑器推荐
  3. POJ 2828 Buy Tickets 线段树
  4. oracle 条件查询,比较运算符,逻辑运算符,特殊运算符,判断空值,大小写敏感,多行,多列子查询...
  5. 一个自己写的PHP模板引擎
  6. poj 3257(哈希+二维dp)
  7. xml注册使用menu
  8. python中的遍历range_python中for用来遍历range函数的方法
  9. QQ的clientkey与淘宝旺旺Token 不同平台环境下的登录认证
  10. 什么叫计算机硬件特征码,如何检测电脑的硬件特征码信息(系统、主板、CPU、硬盘),不使用WMI...
  11. 库和计算机硬盘什么区别是什么,电脑内存和硬盘容量的区别是什么
  12. linux刻录光盘空间不足,Linux下的光盘刻录技巧
  13. python微信抢红包神器_Python自动抢红包教程详解
  14. 润乾报表Api导出word只读
  15. 流媒体:依托于声网的连麦解决方案
  16. C语言基础入门48篇_26_身份证号校验程序(以身份证的校验方式是实例加深对数组及函数封装的理解、字符-‘0‘得到字符对应的int类型数字)
  17. 黑色简洁的PHP短网址短链接生成源码
  18. python 反转字符串
  19. 百慕大将于下周宣布推出加密货币友好银行
  20. 深入解读 Spark 宽依赖和窄依赖(ShuffleDependency NarrowDependency)

热门文章

  1. NB-LOT 常用AT指令集简介
  2. Android屏幕、坐标系、Padding、Margin
  3. python点击屏幕坐标获取_python+appium 点击屏幕坐标操作(qq头像为例)
  4. jquery 常见特效_常见jQuery错误的解决方案
  5. 中国象棋详细设计分析
  6. 网络配置实训(思科)
  7. QT实现界面多语言切换
  8. java dwg转pdf_CAD处理控件Aspose.CAD转换功能演示:使用Java将DWG和DXF文件转换为PDF...
  9. STM32F072RB 实作笔记(一)- Keil 安装
  10. java的hashmap排序_java 中HashMap排序