因实际使用需求我们测试一下网络通讯,在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_t tmp;

uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};

//WIZCHIP SOCKET缓存区初始化

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_t tmpstr[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_t mac[6];  ///< Source Mac Address

uint8_t ip[4];   ///< Source IP Address

uint8_t sn[4];   ///< Subnet Mask

uint8_t gw[4];   ///< Gateway IP Address

uint8_t dns[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_t ret;

uint8_t socketStatus=getSn_SR(sn);

switch(socketStatus)

{

case SOCK_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;

}

case SOCK_CLOSE_WAIT :

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

{

return ret;

}

break;

case SOCK_INIT :

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

{

return ret;

}

break;

case SOCK_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进制发送一条指令,可以看到下方的接收栏中收到数据。

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

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

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

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

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

STM32F412应用开发笔记之五:结合W5500实现以太网通讯的更多相关文章

  1. STM32F412应用开发笔记之十:多组分气体分析仪设计验证

    本次将NUCLEO-F412ZG应用于我们的多组分气体分析仪的实现试验,从整体上测试实际项目的应用情况. 一.项目概述 多组分气体分析仪是我公司近期研发的三个主要产品之一.采用模块化设计,可增减配置, ...

  2. STM32F412应用开发笔记之九:移植FreeRTOS到F412ZG平台

    在开发实际应用系统时,我们经常需要考虑数据的实时性和多任务,嵌入式实时操作系统的出现为实现这一目的提供了很好的助力.FreeRTOS是近年来比较流行的嵌入式实时操作系统,而且是开源免费的,STM32C ...

  3. STM32F412应用开发笔记之一:初识NUCLEO-F412ZG

    今天终于收到了期待已久的NUCLEO-F412ZG,感谢电子发烧友论坛! 近几年来基本都是在STM32平台上做一些设计开发工作.STM32F103.STM32F107.STM32F429等都应用过,但 ...

  4. STM32F412应用开发笔记之三:SPI总线通讯与AD采集

    本次我们在NUCLEO-F412ZG试验模拟量输入采集.我们的模拟量输入采用ADI公司的AD7705,是一片16位两路差分输入的AD采集芯片.具有SPI接口,我们将采用SPI接口与AD7705通讯.两 ...

  5. STM32F412应用开发笔记之二:基本GPIO控制

    NUCLEO-F412ZG板子上的元器件并没有完全焊接,除去ST-LINK部分和电源部分后,还有用一个USB主机接口,三个LED灯和两个按钮,不过很多功能引脚都已经引到了插针.查看原理图可发现,由原理 ...

  6. Modbus库开发笔记之五:Modbus RTU Slave开发

    Modbus在串行链路上分为Slave和Master,这一节我们就来开发Slave.对于Modbus RTU从站来说,需要实现的功能其实与Modbus TCP的服务器端是一样的.其操作过程也是一样的. ...

  7. STM32F412应用开发笔记之六:使用片上Flash存储参数

    我们的项目中需要保存一些系统配置参数,这些数据的特点是:数量少而且不需要经常修改,但又不能定义为常量,因为每台设备可能不一样而且在以后还有修改的可能.这就需要考虑这些参数保存的问题.将这类数据存在指定 ...

  8. STM32F412应用开发笔记之四:与远红外炭氢传感器通讯

    远红外炭氢传感器是在多组分气体传感器中用来检测甲烷和丙烷浓度的,采用单总线串行通讯,TTL电平.所以我们需要用到UART口来实现与远红外炭氢传感器的通讯. 远红外传感器就是这个样子的: 再来一张进气和 ...

  9. STM32F412应用开发笔记之八:迪文串口屏显示驱动

    迪文的显示屏使用起来比较方便,其使用串口通讯,即可支持RS232,又可以支持TTL电平.在NUCLEO-F412ZG实验板上,USART2已经引到了CN9上,我们就利用USART2来实现与迪文串口屏的 ...

随机推荐

  1. TCP/IP协议详解——邮差与邮局

    信号的传输总要符合一定的协议.比如说长城上放狼烟,是因为人们已经预先设定好狼烟这个物理信号代表了“敌人入侵”这一抽象信号.这样一个“狼烟=敌人入侵”就是一个简单的协议. 信号的传输总要符合一定的协议( ...

  2. 北京培训记day1

    数学什么的....简直是丧心病狂啊好不好 引入:Q1:前n个数中最多能取几个,使得没有一个数是另一个的倍数   答案:(n/2)上取整 p.s.取后n/2个就好了 Q2:在Q1条件下,和最小为多少 答 ...

  3. iOS - URL Scheme 操作

    推荐JLRoutes路由跳转 NSScanner 在寻找更加灵活的页面跳转和通知,我遇见了JLRoutes,从而学习使用URL Scheme来定义界面入口.以前从来没有使用过,不过很多大厂和流行的框架 ...

  4. [教程] [授权翻译] 使用补丁修改DSDT/SSDT [DSDT/SSDT综合教程]

    [教程] [授权翻译] 使用补丁修改DSDT/SSDT [DSDT/SSDT综合教程] http://bbs.pcbeta.com/viewthread-1571455-1-1.html [教程] [ ...

  5. cent6.4使用

    让centos能够上网 刚安装了时,是不能联网的,我们可以通过以下命令更改即可: cd /etc/sysconfig/network-script vi ifcfg-eth0 更改其中的ONBOOT= ...

  6. web前端基础知识-(八)Ajax

    Ajax即"Asynchronous Javascript And XML"(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,AJAX = 异步 Ja ...

  7. HTML5的Audio标签打造WEB音频播放器

    目前,WEB页面上没有标准的方式来播放音频文件,大多数的音频文件是使用插件来播放,而众多浏览器都使用了不同的插件.而HTML5的到来,给我们提供了一个标准的方式来播放WEB中的音频文件,用户不再为浏览 ...

  8. wifi万能钥pc版提示手机未连接

     关于PC版万能钥匙的用法 大部分人都是在“未连接到手机”再不知道怎么搞了 怎么连接到手机呢? 首先要把你的手机变成路由器 让电脑连上 这个都知道怎么搞吧 手机版万能钥匙有个一键让手机变成热点 再用电 ...

  9. 列表中checked全选按钮的实现

    用过音乐播放器的人都知道有个全选按钮,如果使用Jquery实现,有个直接选中checked标签的方式 <!DOCTYPE HTML> <html> <head> & ...

  10. ajax传输中文乱码解决方法

    问题描述: 我是在一个jsp页面有一个保存按钮,点击时会触发saveForm()的js函数,在saveForm()函数里经过校验后,会通过ajax发送数据请求,这样就不用通过提交表单来传输数据了,aj ...