FreeModbus 移植笔记- 1-认识FreeModbus

FreeModbus 移植笔记

目录

1 FreeMODBUS介绍

2 FreeMODBUS官网及源码下载地址

3 移植之前的准备

3.1 FreeModbus V1.6

​​​​​​​3.2 Modbus

3.3 Modbus Registers

​​​​​​​3.4 Modbus Configuration

​​​​​​​3.5 Utilities

​​​​​​​3.6 移植和头文件

​​​​​​​3.7 FreeModbus Examples

​​​​​​​3.8 Porting for RTU/ASCII

​​​​​​​3.8.1 创建移植文件及目录

​​​​​​​3.8.2 平台特性(port.h)

​​​​​​​3.8.3 定时器功能实现

​​​​​​​3.8.4 Modbus-RTU/ASCII的移植

​​​​​​​3.8.5 事件队列的实现

​​​​​​​3.9 Tips


​​​​​​​

1 FreeMODBUS介绍

FreeMODBUS 是针对通用的Modbus协议栈在嵌入式系统中应用的一个实现。Modbus协议是一个在工业制造领域中得到广泛应用的一个网络协议。一个Modbus通信协议栈包括两层:定义了数据结构和功能Modbus应用协议和网络层。在FreeMODBUS的当前版本中,提供了Modbus Application Protocol v1.1a 的实现并且支持在Modbus over serial line specification 1.0中定义的RTU/ASCII传输模式。从0.7版本开始,FreeModbus也支持在TCP defined in Modbus Messaging on TCP/IP Implementation Guide v1.0a中定义的TCP传输。Freemodbus遵循BSD[1] ,这意味着本协议栈的实现代码可以应用于商业用途。目前版本的FreeModbus支持如下的功能码:

读输入寄存器 (0x04)

读保持寄存器 (0x03)

写单个寄存器 (0x06)

写多个寄存器 (0x10)

读/写多个寄存器 (0x17)

读取线圈状态 (0x01)

写单个线圈 (0x05)

写多个线圈 (0x0F)

读输入状态 (0x02)

报告从机标识 (0x11)

本实现基于最新的标准并且与标准完全兼容。接收和传输Modbus RTU/ASCII数据帧是通过一个由硬件提取层的调用来驱动状态机来实现的。这就使得该协议非常容易移植到其他的平台之上。当收到一个完整的数据帧后,该数据帧被传入Modbus应用层,数据帧的内容在该层得到解析。为例方便增加新的Modbus功能,Freemodbus在应用层通提供了Hooks。

如果用到了Modbus TCP协议,那么当准备处理一个新数据帧的时候,移植层就必须首先向协议栈发送一个事件标志。然后,协议栈调用一个返回值为接收到的Modbus TCP数据帧的函数,并且开始处理这个数据帧。如果数据有效,则相应的Modbus反馈帧将提供给移植层生成反馈帧。最后,该反馈被发送到客户端。

2 FreeMODBUS官网及源码下载地址

官网地址:https://www.embedded-experts.at/en/freemodbus/about/

源码下载地址:https://www.embedded-experts.at/en/freemodbus-downloads/

3 移植之前的准备

在移植FreeModbus之前,应该先看一下freeModbus的API文档,了解一下freeModbus的接口和使用方法,对freeModbus建立初步认识。

https://www.embedded-experts.at/en/freemodbus/api-documentation/

上面网站可以打开FreeModbus的API文档.

​​​​​​​3.1 FreeModbus V1.6

FreeModbus 移植笔记- 1-认识FreeModbus_第1张图片

 

FreeModbus中简单介绍了FreeModbus版本的演进和功能的增加,然后Port列出了不同类型单片机的移植示例名称。

​​​​​​​3.2 Modbus

FreeModbus 移植笔记- 1-认识FreeModbus_第2张图片

 

Modbus文件中详细说明了mb.h文件中的宏定义,枚举含义,调用的函数已经FreeModbus的使用方法。

重点:FreeModbus的应用方法。

先调用eMBInit(),然后调用eMBEnable()使能协议站,最后在循环中调用eMBPoll()。​​​​​​​

3.3 Modbus Registers

FreeModbus 移植笔记- 1-认识FreeModbus_第3张图片

 

Modbus Register文件中说明了输入寄存器、保持寄存器、线圈、离散输入寄存器各种寄存器回调函数的功能、参数和返回值的含义。

​​​​​​​3.4 Modbus Configuration

FreeModbus 移植笔记- 1-认识FreeModbus_第4张图片

 

Modbus Configuration文件说明了mbconfig.h文件中宏定义的功能,通过对宏定义的配置可实现对FreeModbus的裁剪,如,如果不使用Modbus-ASCII和Modbus-TCP可以配置MB_ASCII_ENABLED(0),MB_TCP_ENABLED(0).

​​​​​​​3.5 Utilities

FreeModbus 移植笔记- 1-认识FreeModbus_第5张图片

 

Utilities文件说明了Modbus中位和字符串数组操作函数的功能和参数返回值。

主要在操作线圈和离散寄存器时使用。

​​​​​​​3.6 移植和头文件

移植和头文件只列举例文件名称。

FreeModbus 移植笔记- 1-认识FreeModbus_第6张图片

 

FreeModbus 移植笔记- 1-认识FreeModbus_第7张图片

 

​​​​​​​3.7 FreeModbus Examples

列举了各类单片机的移植示例代码和说明

FreeModbus 移植笔记- 1-认识FreeModbus_第8张图片

 

​​​​​​​3.8 Porting for RTU/ASCII

描述了modbus移植步骤和需要移植的文件

FreeModbus 移植笔记- 1-认识FreeModbus_第9张图片

 

这部分内容非常重要。

​​​​​​​3.8.1 创建移植文件及目录

第一步,为移植文件创建目录。推荐创建“demo/PLATFORM”的顶层目录,用于存放应用文件和工程文件,在”PLATFORM”的次级文件目录下创建“port”文件夹用于存放FreeModbus移植文件,如下图:

FreeModbus 移植笔记- 1-认识FreeModbus_第10张图片

 

可以直接复制下载的freeModbus的源码中的“demo/BARE”文件夹的内容到新建的工程中,开始移植工作。

​​​​​​​3.8.2 平台特性(port.h)

应该检查一下port.h文件,检查其是否适合当前的平台,并且定义两个宏定义ENTER_CRITICAL_SECTION和EXIT_CRITICAL_SECTION。用于关闭全局中断和打开全局中断。

注意:进入临界区ENTER_CRITICAL_SECTION和退出临界区EXIT_CRITICAL_SECTION主要应用于保护数据的完整性,尤其是使用操作系统后,避免一组数据在读取和写入时别打断而造成数据错位的情况发生。

​​​​​​​3.8.3 定时器功能实现

Modbus协议栈需要一个定时器来检测数据帧的末尾。这个定时器的精度应该是半个字符的传输时间。例如,假设一个字符需要11位,波特率位38400时,一个字符的传输时间大约是280us。两帧数据之间最小的超时时间间隔是3.5个字符传输间隔。

首先应该实现xMBPortTimersInit( USHORT usTim1Timerout50us) 和 vMBPortTimersEnable( )这两个函数。测试代码如下:

FreeModbus 移植笔记- 1-认识FreeModbus_第11张图片

 

在中断函数中调用pxMBPortCBTimerExpired,并且设置一个断点或者反转LED.在调用vMBPortTimersEnable( )之后,应该每隔1ms发生一次中断,最后需要检查vMBPortTimersDisable( )是否工作正常。

注:xMBPortTimersInit( USHORT usTim1Timerout50us)实现的是50us整数倍的定时间隔,参数usTim1Timerout50us用于设置50us的倍数。

​​​​​​​3.8.4 Modbus-RTU/ASCII的移植

串口层的移植需要实现以下功能:串口的初始化、接收功能的使能和失能、发送功能的使能和失能、单个字符的接收和发送回调函数等。

需要实现的函数有:

串口初始化函数xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )。

串口接收发送设置函数vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable ).

此外,还需要创建两个串口的中断服务程序,一个是接收中断,一个是发送中断,通常从接收中断开始创建比较简单。

调用如下代码开始测试接收中断程序,

FreeModbus 移植笔记- 1-认识FreeModbus_第12张图片

 

创建串口接收中断,设置断点并且检查xMBPortSerialGetByte( CHAR * pucByte )是否正确返回了接收到的字符。

串口接收中断如下:

FreeModbus 移植笔记- 1-认识FreeModbus_第13张图片

 

接下来,实现发送中断部分,测试代码如下:

FreeModbus 移植笔记- 1-认识FreeModbus_第14张图片

 

开启要给终端程序,并且在发送缓存空中断中仅调用xMBPortSerialPutByte( 'a' ),发送中断的测试代码如下:

FreeModbus 移植笔记- 1-认识FreeModbus_第15张图片

 

如果上面的功能都测试正常,就可以在portserial.c中逐个实现。

​​​​​​​3.8.5 事件队列的实现

如果你的工程没有使用操作系统,那么事件队列的的实现已经完成。如果您有幸在操作系统中使用FreeModbus协议栈,其不同之处如下:

1、在启动时创建一个任务,在循环中调用eMBPoll(),如下图:

FreeModbus 移植笔记- 1-认识FreeModbus_第16张图片

 

可以参照STR71x对FreeRTOS的移植例子。

2、修改xMBPortEventPost函数,发送一个事件到队列。请注意,此函数将从中断服务程序(ISR)调用,因此请查看RTOS文档

3、修改xMBPortEventGet从队列中接收事件。eMBPoll()会定期去查询队列,直到有事件发送到队列时,eMBPoll都应该是阻塞的。

此外,必须修改串口和定时器中断功能。每当协议处理程序回调函数pxMBFrameCBByteReceived、pxMBFrameCBTransmitterEmpty和pxMBPortCBTimerExpired返回TRUE时,都应在退出ISR后进行上下文切换,因为事件已发布到队列。忘记这样做会导致协议栈的性能降低

​​​​​​​3.9 Tips

Tips文件中说明了如何优化代码的方法。

FreeModbus 移植笔记- 1-认识FreeModbus_第17张图片

 

这部分为使用FreeMODBUS协议栈提供一些使用技巧。

减少存储的使用。

FreeMODBUS对存储的使用情况可以通过下面几个方法改变。这里有几个基础的技巧而且很容易实现。

  1. 斟酌是否同时使用RTU,ASCII和TCP协议。如果不使用,可以在config.h文件中将MB_RTU_ENABLED, MB_ASCII_ENABLED 和MB_TCP_ENABLED分别设置为零。
  2. 如果不需要所有的Modbus功能,可以在mbconfig.h文件中取消,以减小代码量。
  3. 设置mbconfig.h文件中MB_FUNC_HANDLERS_MAX的值,减小支持的功能函数数量。

如果对存储空间有更严格的限制,可以尝试下面几个选项,注意这几个选项对协议栈的特性有影响。

  1. 使用一些编译器指令将函数代码到处理函数的映射到CPU的闪存中。您可以在mb.c在文件的顶部中找到此表。静态变量名为xFuncHandlers。
  2. 减小RTU缓冲区的大小。在这种情况下,较长的帧将导致错误(您的设备将丢弃所有这些帧)。这有可能导致你永远不能读写一部分寄存器或者你的寄存器总量很小。
  3. 还可以删除一些使协议栈可配置的函数指针,并用函数本身替换它们。例如,如果只想使用RTU,可以从移植层删除回调函数并填充适当的调用程序。这可以节省所有函数指针节省空间。

你可能感兴趣的:(modbus,STM32,modbus,stm32,嵌入式硬件)