微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 结合W5500实现以太网通讯

结合W5500实现以太网通讯

时间:10-02 整理:3721RD 点击:

因实际使用需求我们测试一下网络通讯,在NUCLEO-F412ZG测试板上没有以太网部分,我们选择外接一个W5500的实验板。W5500支持SPI接口通讯,DC3.3V供源。而NUCLEO-F412ZG测试板已经将SPI1的各引脚SPI1_NSS(CN7_17)、SPI1_SCK(CN7_10)、SPI1_MISO(CN7_12)、SPI1_MOSI(CN7_14)引出到CN7,3.3VDC和GND也引导了CN8,可以方便的实现测试。如下图红框所示:




1、测试的准备工作


为了实现以太网通讯首先需要下载W5500的驱动源码,可以到WIZnet的官网下载:http://www.iwiznet.cn/


目前最新版本为V1.1,我选用的是V1.03下载下来的压缩包解压后如下图:



需要将ethernet文件夹拷贝到我们的项目目录中:




并在IAR的项目下添加相关的文件和路径,主要是socket.c、w5500.c、wizchip_.conf.c三个文件。这三个文件分别实现socket、硬件驱动及相关通讯配置功能,具体可以查看相应的源码级手册。





2、编写测试代码


在完成以上工作后就可以开始真正地移植工作了。具体步骤如下:


  • 硬件配置及初始化。

  • 以太网通讯配置的初始化。

  • 实现具体的通讯过程。



2.1、硬件的配置及初始化


由于W5500通过SPI接口与STM32通讯,所以硬件配置和初始化是非常简单的,与W5500实际上没有关系,使一些通用的操作。事实上就是STM32F412ZG的SPI接口初始化的过程,需要实现RCC、GPIO以及SPI的初始化就可以了。关于这部分可以查看ST的例程。


2.2、以太网通讯配置的初始化


以太网通讯配置的初始化主要有三个方面的内容:


  • 注册TCP通讯相关的回调函数  RegisterFunction();

  • 初始化芯片参数  ChipParametersConfiguration();

  • 初始化网络通讯参数  NetworkParameterConfiguration()



三个函数的具体实现内容如下:


//函数注册,首先,应由用户实现SPI注册回调函数来访问WIZCHIP


void RegisterFunction(void)


{  


  //临界区回调函数


reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);  //注册临界区函数


  //片选回调函数


#if  _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_


reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);//注册SPI片选信号函数


#elif _WIZCHIP_IO_MODE_ ==_WIZCHIP_IO_MODE_SPI_FDM_


  reg_wizchip_cs_cbfunc(SPI_CS_Select,SPI_CS_Deselect);  // CS必须为低电平.


#else


   #if(_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_


     #error "Unknown _WIZCHIP_IO_MODE_"


   #else


     reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);


   #endif


#endif


  //SPI的读写回调函数


reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);     //注册读写函数


}


注册函数实际上就是函数指针的调用,可参考C语言函数指针部分内容。对于以上注册的函数,SPI_WriteByte需要说明一下,无论是用可函数还是直接操作寄存器,在写完之后都需要再读一下(红色部分),否则就会在客户端出现连接TCPServer超时的报警,没明白什么原因。


//写1字节数据到SPI总线


void SPI_WriteByte(uint8_t TxData)


{                        


// while((SPI2->SR&SPI_I2S_FLAG_TXE)==0);        //等待发送区空               


// SPI2->DR=TxData;                              //发送一个byte


// while((SPI2->SR&SPI_I2S_FLAG_RXNE)==0);       //等待接收完一个byte  


// SPI2->DR;


while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);        //等待发送区空


SPI_I2S_SendData(SPI2,TxData);                                        //发送一个byte


while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET);        //等待接收完一个byte


SPI_I2S_ReceiveData(SPI2);                                            //返回接收的数据


}




//初始化芯片参数


void ChipParametersConfiguration(void)


{


  uint8_ttmp;


  uint8_tmemsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};


  //WIZCHIPSOCKET缓存区初始化


if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1){


   //printf("WIZCHIP Initialized fail.\r\n");


  while(1);


  }



  //PHY物理层连接状态检查


  do{


   if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1){


     //printf("Unknown PHY Link stauts.\r\n");


    }


}while(tmp == PHY_LINK_OFF);


}


以上实现网络物理层的配置。


//初始化WIZCHIP中的网络参数信息


void NetworkParameterConfiguration(void)


{


  uint8_ttmpstr[6];


ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);


ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO);



ctlwizchip(CW_GET_ID,(void*)tmpstr);


}



其中gWIZNETINFO是一个wiz_NetInfo类型的结构体变量,该结构体在wizchip_conf.h中定义,用于设置mac地址、IP地址等网络参数,具体如下:


typedef struct wiz_NetInfo_t


{


   uint8_tmac[6];  ///< Source Mac Address


   uint8_tip[4];   ///< Source IP Address


   uint8_tsn[4];   ///< Subnet Mask


   uint8_tgw[4];   ///< Gateway IP Address


   uint8_tdns[4];  ///< DNS server IP Address


  dhcp_mode dhcp;  ///< 1 -Static, 2 - DHCP


}wiz_NetInfo;


至此网络部分的初始化就已完成。


2.3、具体通讯过程的实现


经过前面的配置网络已经可以ping通了,下面可以实现具体的应用。对于我这个项目就是可是实现Modbus TCP的编写了。


编写TCP Server,这部分有很多资料,直接附代码:


//TCP服务器数据通讯


int32_t TCPServer(uint8_t sn, uint16_t port)


{


  int32_tret;


  uint8_tsocketStatus=getSn_SR(sn);



switch(socketStatus)


  {


    caseSOCK_ESTABLISHED :


      {


       if(getSn_IR(sn) & Sn_IR_CON)


        {


         setSn_IR(sn,Sn_IR_CON);


        }


       uint16_t size=0;


       if((size = getSn_RX_RSR(sn)) > 0)


        {


         if(size > DATA_BUFFER_SIZE)


          {


           size = DATA_BUFFER_SIZE;


          }


         uint8_t rxBuffer[DATA_BUFFER_SIZE];


         ret = recv(sn,rxBuffer,size);


         if(ret <= 0)


          {


           return ret;


          }


         //添加数据解析及响应的函数


         uint8_t txBuffer[DATA_BUFFER_SIZE];


         uint16_t length=ReceivedDataParsing(rxBuffer,txBuffer);


         


         uint16_t sentsize=0;


         while(length != sentsize)


          {


           ret = send(sn,txBuffer+sentsize,length-sentsize);


           if(ret < 0)


           {


             close(sn);


             return ret;


           }


           sentsize += ret; // 不用管SOCKERR_BUSY, 因为它是零.


          }


        }


       break;


      }


    caseSOCK_CLOSE_WAIT :


     if((ret=disconnect(sn)) != SOCK_OK)


      {


       return ret;


      }


     break;


    caseSOCK_INIT :


      if((ret = listen(sn)) != SOCK_OK)


      {


       return ret;


      }


     break;


    caseSOCK_CLOSED:


     if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)


      {


       return ret;


      }


     break;


   default:


     break;


  }


  return 1;


}



其中ReceivedDataParsing(rxBuffer,txBuffer)实现具体的应用协议,根据具体的需求而定,在此我们实现了简单的Modbus TCP协议。


3、测试结果


完成编写,调试无误后,将程序下载到目标板,首先既然是以太网通讯,我们就在上位机上机简单的网络测试。在目标板上我们设定的IP地址为:192.168.1.100,在CMD中使用简单的Ping命令测试如下:




由上图可以看到,网路没有问题。接下来我们用TCP&UDP测试工具进行进一步的测试,并使用Microsoft Network Monitor监视数据包。打开TCP&UDP测试工具,创建一个TCP客户端,目标IP还是目标板IP,端口用502(我们在软件中设定了)。




创建完成后,连接无误,在发送栏中以16进制发送一条指令,可以看到下方的接收栏中收到数据。




我们再看看MicrosoftNetwork Monitor中捕获到的数据包核对一下数据是否正确。




由于我们实现了简单的Modbus TCP协议,所以我们在使用ModScan32来测试一下通讯是否正确。首先启动ModScan32,并做如下配置:




连接后数据显示出来,持续更新一段时间后没有问题。




同样,我们再看看MicrosoftNetwork Monitor中捕获到的数据更新与ModScan32做一对比,数据包完整而且正确。



完成测试,通讯没有问题STM32F412与W5500实现以太网通讯简单方便。

牛逼都是用寄存器。

现在手上都没有网络模块。

网上有卖的,价格也不贵,SPI接口很方便!

学习,,,,,,,,,,,学习

大神,我现在弄STM8S和W5500的spi,我是新手,那个时钟怎么配置,多少分频啊,传输数据的代码都弄好了,就剩下时钟配置和定时器配置,能否指教一下,谢谢啦,我搞了好久实在没法把资料联系起来

我想实现仪器主板与笔记本或电脑数据连接,不知道能否提供有偿技术支持

你采用的什么通讯协议?只要你的协议可以开放就没有问题!如果是自定义的协议,上位软件就需要开发,如果是标准协议,你就可以找到相应的上位软件。当然,如果你想让它完全是你自己的版权,也可以自己开发!
若有需要,可以联系我们!
QQ:7877937945
邮箱:yinjj@comity-tec.com

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top