基于STM32和W5500的Modbus TCP通讯



在最近的一个项目中需要实现Modbus TCP通讯,而选用的硬件平台则是STM32F103和W5500,软件平台则选用IAR EWAR6.4来实现。

1、移植前的准备工作

为了实现Modbus TCP通讯首先需要下载W5500的驱动源码,可以到WIZnet的官网下载:products:w5500:driver [Document Wiki]

下载下来的压缩包,解压后如下图:

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

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

并在如下图所示的项目选项设置中添加Ethernet和Ethernet\W5500目录。

2、移植过程和代码编写

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

  • 硬件配置及初始化。

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

  • 实现具体的通讯过程。

2.1、硬件的配置及初始化

由于W5500通过SPI接口与STM32通讯,所以硬件配置和初始化是非常简单的,与W5500实际上没有关系,使一些通用的操作。事实上就是STM32F103的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_"#elsereg_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);                                       //发送一个bytewhile(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET);       //等待接收完一个byteSPI_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 Addressuint8_tip[4];  ///< Source IP Addressuint8_tsn[4];  ///< Subnet Maskuint8_tgw[4];  ///< Gateway IP Addressuint8_tdns[4]; ///< DNS server IP Addressdhcp_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;//基于STM32和W5500的Modbus TCP通讯
}

其中ReceivedDataParsing(rxBuffer,txBuffer)实现具体的Modbus协议,根据具体的需求而定。

通过Modscan连接测试,结果正确。

欢迎关注:

 实例下载:ModbusExample.zip-其它文档类资源-CSDN下载

实例说明:Modbus协议栈综合实例设计_木南创智-CSDN博客

同时发到Github,其地址为:https://github.com/foxclever/Modbus
同时也发布到码云,其地址为:https://gitee.com/ErichMoonan/Modbus
在开源的协议栈中example文件夹下即是本次发布的例子。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python小练习1:.txt文件常用读写操作

.txt文件常用读写操作 本文通过一个实例来介绍读写txt文件的各种常用操作&#xff0c;问题修改自coursera上南京大学的课程&#xff1a;用Python玩转数据。 直接进入正题&#xff0c;考虑下面为练习读写txt文件的各种操作而设计的一个具体问题 问题如下&#xff1a; (1) 在任意…

STM32F103使用内部Flash保存参数

&#xfeff;&#xfeff; 在我们应用开发时&#xff0c;经常会有一些程序运行参数需要保存&#xff0c;如一些修正系数。这些数据的特点是&#xff1a;数量少而且不需要经常修改&#xff0c;但又不能定义为常量&#xff0c;因为每台设备可能不一样而且在以后还有修改的可能。…

FreeRTOS学习及移植笔记之一:开始FreeRTOS之旅

&#xfeff;&#xfeff; 1、必要的准备工作 工欲善其事&#xff0c;必先利其器&#xff0c;在开始学习和移植之前&#xff0c;相应的准备工作必不可少。所以在开始我们写要准备如下: 测试环境&#xff1a;我准备在STM32F103平台上移植和测试FreeRTOS系统 准备FreeRTOS系统…

FreeRTOS学习及移植笔记之二:在IAR和STM32F103VET上移植FreeRTOS

&#xfeff;&#xfeff;上一次&#xff0c;我们简单的测试了FreeRTOS的基于IAR EWARMv6.4和STM32F103VET6平台的Demo&#xff0c;对其有了一个基本认识。接下来我们开始自己移植FreeRTOS的过程。 1、创建一个“FreeRTOSTestProject”项目文件夹&#xff0c;并在其下创建FreeR…

如何创建一个最简单的Windows桌面应用程序 (C++)

如何创建一个最简单的Windows桌面应用程序 (C) 最近刚开始学习C/C开发Windows应用程序&#xff0c;这里将会以零基础的视角把学习过程完全记录下来。如果你也刚刚起步&#xff0c;那本文一定非常适合你。 进入正题&#xff0c;本文讨论如何使用Visual Studio生成一个最简单的C窗…

Win32窗体应用程序如何添加资源文件?

Win32窗体应用程序如何添加资源文件&#xff1f; 上一篇文章介绍了&#xff1a;如何创建一个最简单的Windows窗体应用程序。 按照上一篇文章的介绍&#xff0c;我们的HelloApp项目对应如下的窗体应用程序&#xff1a; 这一篇文章中&#xff0c;我们将在这个程序的基础上&#x…

【论文党福利】如何提取图像中的数据

【论文党福利】如何提取图像中的数据 从事科研的老师和同学们在撰写论文时&#xff0c;经常需要将文献中的曲线与自己的结果进行对比&#xff0c;为获取原始数据&#xff0c;最靠谱的方法当然是找原作者要。如果没有要到呢&#xff1f;本文将成为论文党的福利&#xff0c;为你…

添加串口和虚拟终端输出帮助调试

&#xfeff;&#xfeff;在使用IAR开发STM32项目时&#xff0c;使用串口或者是虚拟终端来输出我们想看的信息是一个非常好而且简便的方式。 首先来看看串口怎么实现信息输出。简单来说串口输出信息就是将标准输出重定向到串口&#xff0c;在上位机的超级终端或者串口助手等工…

1.1股票数据预处理练习

第一阶段、一个简单策略入门量化投资 1.1股票数据预处理练习 无论我们要对股票市场进行何种探索&#xff0c;在开始前&#xff0c;研究如何获取数据&#xff0c;并进行对应的预处理都是必要的。 本节以美股为例&#xff0c;进行股票数据预处理的练习。正文如下&#xff1a; …

1-2 移动均线交叉策略1

第一阶段、一个简单策略入门量化投资 1-2 移动均线交叉策略1 第一阶段一个简单策略入门量化投资1-2 移动均线交叉策略1前言获取数据移动均线交叉策略数据可视化绘制折线图绘制K线图绘制移动均线 移动均线交叉策略回测什么是回测回溯买卖信号计算收益 未完待续完整代码 前言 …

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

&#xfeff;&#xfeff;今天终于收到了期待已久的NUCLEO-F412ZG&#xff0c;感谢电子发烧友论坛&#xff01; 近几年来基本都是在STM32平台上做一些设计开发工作。STM32F103、STM32F107、STM32F429等都应用过&#xff0c;但却从没有申请过试用。没想到这次申请居然能被选中&a…

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

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

1-3移动均线交叉策略2

第一阶段、一个简单策略入门量化投资 1-3移动均线交叉策略2 上一篇文章1-2 移动均线交叉策略1中我们最后提到&#xff1a; 如果我们从第一天买入股票&#xff0c;一直持有股票&#xff0c;最后一天卖出&#xff0c;获得的收益是每股124.02美元&#xff0c;收益率为412% 如果…

1-4移动均线交叉策略3

第一阶段、一个简单策略入门量化投资 1-4移动均线交叉策略3 上一文1-3移动均线交叉策略2中&#xff0c;我们得到的结果是令人失望的。但我们的探索还要继续。 我们知道&#xff0c;使用投资组合的方式进行分散投资是降低风险的好办法。尽管移动均线交叉策略的表现并不理想&a…

STM32学习及应用笔记一:SysTick定时器学习及应用

&#xfeff;&#xfeff; 这几年一直使用STM32的MCU&#xff0c;对ARM内核的SysTick计时器也经常使用&#xff0c;但几乎没有仔细了解过。最近正好要在移植一个新的操作系统时接触到了这块&#xff0c;据比较深入的了解了一下。 1、SysTick究竟是什么&#xff1f; 关于SysT…

使用Atom快速打造好用的Markdown编辑器

使用Atom快速打造好用的Markdown编辑器 Atom当前主流的跨平台的三大编辑器(Atom,sublime,vscode)之一 今天尝试了使用Atom来打造Markdown编辑器&#xff0c;快速上手且易用&#xff0c;墙裂推荐&#xff01; 下面直接进入正题&#xff0c;一步步介绍如何使用Atom快速打造好用…

PID控制器开发笔记之一:PID算法原理及基本实现

&#xfeff;&#xfeff; 在自动控制中&#xff0c;PID及其衍生出来的算法是应用最广的算法之一。各个做自动控制的厂家基本都有会实现这一经典算法。我们在做项目的过程中&#xff0c;也时常会遇到类似的需求&#xff0c;所以就想实现这一算法以适用于更多的应用场景。…

十分钟能学会的简单python爬虫

简单爬虫三步走&#xff0c;So easy~ 本文介绍一个使用python实现爬虫的超简单方法&#xff0c;精通爬虫挺难&#xff0c;但学会实现一个能满足简单需求的爬虫&#xff0c;只需10分钟&#xff0c;往下读吧~ 该方法不能用于带有反爬机制的页面&#xff0c;但对于我这样的非专业…

PID控制器开发笔记之二:积分分离PID控制器的实现

前面的文章中&#xff0c;我们已经讲述了PID控制器的实现&#xff0c;包括位置型PID控制器和增量型PID控制器。但这个实现只是最基本的实现&#xff0c;并没有考虑任何的干扰情况。在本节及后续的一些章节&#xff0c;我们就来讨论一下经典PID控制器的优化与改进。这一节我们首…

利用python实现短信和电话提醒功能

有时候&#xff0c;我们需要程序帮我们自动检测某些事件的发生 这个需求是广泛存在的 因此&#xff0c;这里整理了利用python实现短信和电话提醒功能的方法 主要需要完成以下4个步骤&#xff1a; - 安装核心库&#xff1a;twilio - 注册账号及配置 - 发送短信示例 - 电话…