日期:2014-05-16  浏览次数:20453 次

基于EncEthernet的FreeModbus-TCP 在stm32上的移植与测试

基于EncEthernet的FreeModbus-TCP

在stm32上的移植与测试

DanielLee_USTB  2013-3-27

QQ:382899443

       昨天移植好了modbus-RTU,今晚开始在EncEthernet上的free modbus-TCP的移植,使用的开发板为火牛开发板,stm32f103+enc28j60网络方案。主流的TCP/IP协议栈包括uIP、LwIP等,EncEthernet协议栈是一款比较简单的协议栈,由厂家提供在stm32的开发板已经移植好,所以就直接使用,其他的协议的移植方法应该都大同小异。

       一、相关知识

       Modbus TCP/IP数据帧除了TCP已经有的包头外,还有modbus TCP协议数据单元(ADU),包括MBAP帧头以及与RTU数据内容相同的应用数据单元(PDU),地址码除外。

       其中与单纯的TCP/IP或是modbus-RTU相比,多的内容就是一个MBAP报文头,这是个什么东西,规定了什么内容呢?先来看看都包含哪些东西。

MBAP报文头定义

       可以看出来,MBAP报文头主要添加了以下附加信息,为了识别是请求还是响应而设置的事务元标识符、为了判断协议类型设置的协议标识符、为了区分可变长度数据帧结束的数据帧长度、还有用于标识从站地址,与RTU不同的是,从地址放在了MBAP帧头里。

       二、代码移植

       前两天已经基于BARE工程移植好RTU模式,仿照相应思路实现TCP的一些函数功能,在mbtcp.c中可以发现,包括TCP初始化(xMBTCPPortInit)、TCP启动(eMBTCPStart)、TCP停止(eMBTCPStop)、TCP接收一个数据包(xMBTCPPortGetRequest)、TCP发送一个数据包(xMBTCPPortSendResponse)等,为了实现free-modbus与EncEthernet对接,在port文件夹下建立porttcp.c文件,在其中包含头文件ip_arp_udp_tcp.h。

       (1) xMBTCPPortInit( ucTCPPort )

       这是以太网TCP端口初始化函数,怎么觉得参数有点少呢,绑定TCP端口至少需要mac地址、ip地址以及端口地址吧,这里面只与端口有关,看来只能把他们隐藏了。

       于是加入

       enc28j60Init(mymac);

       enc28j60PhyWrite(PHLCON,0x476);

       init_ip_arp_udp_tcp(mymac,myip,mywwwport);

       这个几个函数作为TCP端口初始化。

      (2) eMBTCPStart

      其实在EncEthernet中只要进行了协议栈的初始化,就已经启动了协议栈,可直接使用。

      (3) eMBTCPStop

这个函数是作为TCP端口关闭的函数,其实在modbus中调用它的是eMBClose,而在协议中没有调用eMBClose把modbus给关掉,所以这个函数不用去实现。

      (4) xMBTCPPortGetRequestTCP接收一个数据包

调用enc28j60PacketReceive(BUFFER_SIZE, buf)进行判断,当然希望移植的modbus除了能处理modbus-TCP包外还能对一些正常数据包进行响应,比如arp请求、ping命令等,所以在之后添加了包头验证,当确定传入包是有