一概述

Modbus是由Modicon(现为施耐德电气公司的一个品牌)在1979年发明的,是全球第一个真正用于工业现场的总线协议。ModBus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监控。为更好地普及和推动Modbus在基于以太网上的分布式应用,目前施耐德公司已将Modbus协议的所有权移交给IDA(InterfaceforDistributedAutomation,分布式自动化接口)组织,并成立了Modbus-IDA组织,为Modbus今后的发展奠定了基础。

在中国,Modbus已经成为国家标准,并有专业的规范文档,感兴趣的可以去查阅相关的文件,详情如下:标准编号为:GB/T19582-2008文件名称:《基于Modbus协议的工业自动化网络规范》,主要包含三个部分:

第1部分:Modbus应用协议

第2部分:Modbus协议在串行链路上的实现指南

第3部分:Modbus协议在TCP/IP上的实现指南

二Modbus的作用

Modbus协议是一种通信协议,而且是一种开放协议,因此广泛地用于在工业自动化系统中实现设备之间的数据交换。它是最常用的串行通信协议之一,广泛应用于监控和控制设备之间的通信。简而言之,它是用于在电子设备之间的串行线路上传输信息的方法。请求信息的设备被称为Modbus客户端,提供信息的设备是Modbus服务器。Modbus支持单主机,多个从机,在标准Modbus网络中,有一个客户端和多达247个服务器,每个服务器都有从1到247的唯一服务器地址。客户端还可以向服务器写入信息。

Modbus通常用于从仪器和控制设备传输信号到主控制器或数据采集系统,例如用于测量温度和湿度并将结果传输到计算机的系统。Modbus通常用于将监控计算机与远程终端单元(RTU)连接在一起,这在监控和数据采集(SCADA)系统中使用。

Modbus协议简单易于实现,传输效率高,因此在工业自动化领域得到广泛应用。它支持多个设备之间的并行通信,可以实现分布式控制系统的互联互通。同时,Modbus协议还具有跨平台、跨厂商的特点,使得不同厂商

三Modbus的工作原理

1、四种数据类型

Modbus协议规定,进行读写操作的数据类型,按照读写属性和类型可分为以下4种:

内存区块

数据类型

主设备访问

从设备访问

内容

离散量输入

布尔

只读

读写

I/O系统提供这种类型数据

线圈

布尔

读写

读写

通过应用程序改变这种类型数据

输入寄存器

无符号双字节整型

只读

读写

I/O系统提供这种类型数据

保持寄存器

无符号双字节整型

读写

读写

通过应用程序改变这种类型数据

2、三种工作模式

Modbus协议主要有三种形式:ModbusASCII、ModbusRTU和ModbusTCP/IP。ModbusASCII和ModbusRTU是基于串行通信的协议,而ModbusTCP/IP则是基于以太网的协议。

ModbusASCII是一种文本协议,使用ASCII码表示数据。它使用起始字符(“:”)、从站地址、功能码、数据、结尾字符(换行符CR/LF)等字段来定义通信内容,并采用的是LRC校验算法。数据以ASCII码的形式传输,通常是通过RS-232或RS-485等串行通信接口进行传输。

ModbusRTU是一种二进制协议,使用二进制码表示数据。它采用起始字符、从站地址、功能码、数据等字段来定义通信内容,并使用CRC校验位来保证数据的完整性。ModbusRTU通常通过RS-232、RS-485或RS-422等串行通信接口进行传输。

ModbusTCP/IP是一种基于以太网的协议,使用TCP/IP协议栈进行通信。它使用以太网帧作为数据传输的封装,通过IP地址和端口号来标识设备。其占用的是502端口,数据帧主要包括两部分:MBAP(报文头)+PDU(帧结构),数据块与串行链路是一致的。ModbusTCP/IP可以通过以太网、无线局域网等网络介质实现设备之间的远程通信。

3、三类功能码

Modbus协议定义了一系列功能码,用于读取和写入设备的寄存器。常用的功能码包括读取保持寄存器、读取输入寄存器、写单个保持寄存器等。通过组合使用功能码和寄存器地址,可以实现对设备的读取和控制操作。

Modbus主要包括3类功能码:公共功能码、用户定义功能码和保留功能码。

3.1标志功能码

0类代码

0类代码通常被认为是有效Modbus设备的最低配置,因为此类代码可使主设备能够读取或写入数据模型。

代码

说明

3

读取多寄存器

16

写入多寄存器

1类代码1类功能码由访问所有类型的数据模型所需的其他代码组成。在原始定义中,此列表包含功能码7(读取异常)。但是,当前规范规定此代码为仅限于串行的代码。

代码

说明

1

读取线圈

2

读取离散量输入

4

读取输入寄存器

5

写入单个线圈

6

写入单个寄存器

7

读取异常状态(仅限串行)

2类代码2类功能码表示不太常用但更为专业化的功能。例如,读取/写入多个寄存器可能有助于减少请求-响应周期的总数,但该行为仍可用0类代码实现。

代码

说明

15

写入多个线圈

20

读取文件记录

21

写入文件记录

22

屏蔽写入寄存器

23

读取/写入多个寄存器

24

读取

3.2Modbus封装接口

Modbus封装接口(MEI)代码(即功能43)用于封装Modbus数据包内的其他数据。目前,提供了两个MEI编号,即13(CANopen)和14(设备识别)。

功能43/14(设备识别)非常有用,因为它允许传输多达256个唯一的对象。其中一些对象已预定义并预留,例如供应商名称和产品代码,但应用程序可以将其他对象定义为作为通用数据集传输。

此类代码并不常用。

3.3异常

从设备使用异常来指示各种不良状况,比如错误请求或不正确输入。但是,异常也可以作为对无效请求的应用程序级响应。从设备不会响应发出异常的请求,而是忽略不完整或损坏的请求,并开始等待新的消息传入。

异常以定义好的数据包格式报告给用户。首先,将功能码返回给等同于原始功能码的请求主设备,设置最高有效位的情况除外。这等同于为原始功能码的值加上0x80。异常响应包括一个异常码,用于代替与给定功能响应相关的正常数据。

异常码

含义

01

不支持接收的功能码。要确认原始功能码,请从返回值中减去0x80。

02

请求尝试访问的地址无效。根据标准,只有在起始地址和所请求值的编号超过216时才会发生这种情况。但是,有些设备可能会限制其

03

请求包含不正确的数据。在某些情况下,这意味着参数不匹配,例如所发送寄存器的数量与“字节总数”字段之间的参数不匹配。更常见的情况是,主设备请求的数据高于从设备或协议所允许的上限。例如,主设备一次只能读取125个保持寄存器,而资源受限的设备可能会将此值限制为更少的寄存器。

04

尝试处理请求时发生不可恢复的错误。这是一个常见异常码,表示请求有效,但从设备无法执行该请求。

每个功能码的状态图至少应包含异常码01,通常包含异常码02、03、04,并且任何其他定义的异常码都是可选的。

四Modbus协议层

在最初的做法中,Modbus是建立在串行端口之上的单一协议,因此它不能被分成多个层。随着时间的推移,该协议引入了不同的应用数据单元,来更改串行通信所用的数据包格式,或允许使用TCP/IP和UDP网络。这样便实现了核心协议和网络层的分离,前者用于定义协议数据单元(PDU),后者用于定义应用数据单元(ADU)。

4.1协议数据单元

PDU及其处理代码构成了Modbus应用协议规范的核心。该规范定义了PDU的格式、协议使用的各种数据概念、如何使用功能码访问数据,以及每个功能码的具体实现和限制。

ModbusPDU格式可定义为功能码,后跟一组关联数据。该数据的大小和内容由功能码定义,整个PDU(功能码和数据)的大小不能超过253个字节。每个功能码都有一个特定的行为,从设备可以根据所需的应用程序行为灵活地实现这些行为。PDU规范定义了数据访问和操作的核心概念;但是,从设备可能会以规范中未明确定义的方式处理数据。

PDU由一个单字节的功能码组成,后跟多达252字节的功能特定数据。

功能码是第一个需要验证的项。如果用于接收请求的设备未识别功能码,则会返回异常。如果功能码被接受,则从设备会根据功能定义开始分解数据。

由于数据包大小限制为253字节,因此设备可传输的数据量有限。最常见的功能码可以在从数据模型中传输240到250字节的实际数据,具体取决于代码。

由于数据包大小限制为253字节,因此设备可传输的数据量有限。最常见的功能码可以在从数据模型中传输240到250字节的实际数据,具体取决于代码。

4.2访问数据

一般来说,Modbus可访问的数据存储在前面所提到的四个数据库或地址范围中的其中一个:线圈、离散量输入、保持寄存器和输入寄存器。与许多规范一样,这些名称可能因行业或应用而异。例如,保持寄存器可能称为输出寄存器,线圈可能称为数字或离散量输出。这些数据库定义了所包含数据的类型和访问权限。从设备可以直接访问这些数据,因为这些数据由设备本地托管。Modbus可访问的数据通常是设备主存的一个子集。相反,Modbus主设备必须通过各种功能码请求访问这些数据。

通过这些区块,我们可以限制或允许访问不同的数据元素,还可以在应用层提供简化的机制来访问不同的数据类型。

这些区块是完全概念性的。它们可能作为独立的内存地址存在于给定的系统中,但也可能重叠。例如,线圈1可能存在于与保持寄存器1所代表的字的第一位相同的内存中。寻址方案完全由从设备定义,其对每个内存区块的解释是设备数据模型的重要组成部分。

4.3数据模型寻址

该规范将每个区块定义为包含多达65536个元素的地址空间。在PDU的定义中,Modbus定义了每个数据元素的地址,范围是从0到65535。然而,每个数据元素的编号从1到n,其中n的最大值为65536。也就是说,线圈1位于地址0的线圈区块中,而保持寄存器54位于从设备定义为保持寄存器的内存部分中的地址53。

规范允许的全部范围不需要给定设备实现。例如,设备可能会选择不执行线圈、离散量输入或输入寄存器,而只使用保持寄存器150至175和200至225。这是完全可以接受的,而且可以通过例外来处理无效的访问尝试。

4.3.1数据寻址范围

虽然规范将不同的数据类型定义为存在于不同的区块中,并为每种类型分配一个本地地址范围,但这并不一定能转化为用于记录或了解给定设备的Modbus可访问内存的直观寻址方案。为了简化对内存区块位置的理解,我们引入了一种编号方案,即向所讨论数据的地址中添加前缀。

例如,在设备手册中,数据项不会表示为位于地址13的保持寄存器14,而是表示为位于地址4014、40014或400014的数据项。在这几种情况中,第一个数字都是4,表示保持寄存器,其余数字则用于指定地址。4XXX、4XXXX和4XXXXX的区别取决于设备所用的地址空间。如果65,536个寄存器全部都在使用,应该使用4XXXXX符号,因为它支持400,001到465,536的范围。如果只有几个寄存器在使用,通常的做法是使用4,001到4,999的范围。

在这种寻址方案中,每种数据类型都被分配了一个前缀,如下表所示。

数据区块

前缀

线圈

0

离散量输入

1

输入寄存器

3

保持寄存器

4

线圈的前缀为0,这意味着4001的引用可能是指保持寄存器1或线圈4001。出于这个原因,建议所有的新实现都使用带前导零的6位数寻址,并在记录时注明这一点。因此,保持寄存器1的地址为400001,而线圈4001的地址则为004001。

4.3.2数据地址起始值

内存地址和引用编号之间的差异会因给定应用程序选择的索引而进一步复杂化。如前所述,保持寄存器1位于地址0。通常,引用编号索引从1开始,这意味着给定范围的起始值为1。因此,400001即表示位于地址0的保持寄存器00001。一些实现选择以0作为范围起始值,即400000表示位于地址0的保持寄存器。下表展示了这个概念。

地址

寄存器编号

编号(索引从1开始,标准)

编号(索引从0开始,备选)

0

1

400001

400000

1

2

400002

400001

2

3

400003

400002

从1开始的索引范围应用较为广泛,强烈建议采用这种方案。无论哪种情况,每个范围的起始值都应在记录时注明。

4.4大数据类型

Modbus标准提供了一个相对简单的数据模型,该模型不包含除无符号双字节整型和位值之外的其他数据类型。如果系统的位值对应于螺线管和继电器,并且双字节整型值对应于未缩放的ADC值,上述模型便已足够;但对于更高级的系统,则无法满足需求。

因此,许多Modbus实现都包含跨寄存器边界的数据类型。NILabVIEW数据记录和监控(DSC)模块以及KEPServerEX都定义了许多引用类型。例如,存储在保持寄存器中的字符串应遵循标准格式(400,001),但后跟一个十进制数、长度和字符串的字节序(400001.2H是指保持寄存器1中包含两个字符的字符串,其中高位字节对应到字符串的第一个字符)。这是必需的,因为每个请求的大小都是有限的,所以Modbus主设备必须知道字符串的确切范围,而不是搜索长度或分隔符(如NULL)。

4.4.1位访问

除了允许访问跨寄存器边界的数据之外,一些Modbus主设备还支持对寄存器中各个位的引用。由于允许设备将相同内存范围内的每种类型的数据组合在一起,而不必将二进制数据分成线圈和离散量输入范围,因此该功能非常有益。通常使用小数点和位索引或编号进行索引,具体取决于如何实现。也就是说,第一个寄存器的第一位可能是400,001.00或400,001.01。建议所有文档均说明所使用的索引方案。

4.4.2数据字节序

通过将数据拆分到两个寄存器,多寄存器数据(如单精度浮点值)可以轻松地通过Modbus进行传输。由于这不是由标准定义的,因此此类拆分的字节序未作规定。尽管每个无符号双字节整型必须以网络(大端)字节序发送才能满足标准,但许多设备会颠倒多字节数据的字节序。下图所示的范例虽然不太常见,但有效地展示了这一观点。

4.4.3字符串

字符串可以轻松地存储在Modbus寄存器中。为了简单起见,某些实现方法要求字符串长度为2的倍数,并使用空值来填充额外的空间。字节序也是字符串交互中的一个变量。字符串格式可能包含也可能不包含NULL(作为最终值)。举个例子,一些设备的数据存储方法可能如下图所示。

4.5从设备功能执行

正如由数据模型所定义,不同的功能会访问不同的概念数据块。一种常见的做法是让代码访问静态内存位置,但其他行为仍然可用。例如,功能码1(读取线圈)和3(读取保持寄存器)可以访问内存中相同的物理位置。而功能码3(读取保持寄存器)和16(写入保持寄存器)可以访问内存中完全不同的位置。因此,建议在定义从数据模型时考虑每个功能码的执行情况。

无论执行的是何种实际行为,所有从设备都应遵循每个请求的简单状态图。下图是功能码1(读取线圈)的状态图范例。

每个从设备必须验证功能码、输入数量、起始地址、总范围以及实际进行读取行为的从属定义功能的执行。

尽管上面的状态图包含了静态地址范围,但真实系统的需求可能会导致静态地址范围与所定义编号有所不同。在某些情况下,从设备无法传输协议所定义的最大字节数。也就是说,如果主设备请求0x07D0输入,从设备只能用0x0400进行响应。同样,从数据模型能够将可接受线圈值的范围定义为地址0到500。如果主设备从地址0开始请求125,则没有问题,但如果主设备从地址400开始发出相同的请求,最后一个线圈将位于地址525,这无疑超出了该设备的范围,因而会出现状态图所定义的异常02。

4.6应用数据单元

除了Modbus协议的PDU核心所定义的功能外,我们还可以使用多种网络协议。最常见的协议是串行和TCP/IP,但也可以使用UDP等其他协议。为了在这些层之间传输Modbus所需的数据,Modbus包含一组专为每种网络协议量身定制的ADU。

4.6.1通用特征

Modbus需要特定的功能来提供可靠的通信。每种ADU格式都需要使用单元ID或地址,以便为应用层提供路由信息。每个ADU都带有一个完整的PDU,其中包含给定请求的功能码和相关数据。为了保证可靠性,每条消息都包含错误检查信息。最后,所有的ADU都提供了一种机制来确定请求帧的开始和结束,但实现方式各不相同。

4.6.2标准格式

ADU的三种标准格式分别是TCP、远程终端单元(RTU)和ASCII。RTU和ASCIIADU通常用于串行线路,而TCP则用于现代TCP/IP或UDP/IP网络。

无论是三种传输模式中的哪一种,Modbus帧格式都是一样的:

Modbus数据帧主要包括:

地址域:1字节,即从机设备地址,通常1-247为有效地址,0为广播地址

功能码:1字节,表明主机请求数据的类型。

数据:N字节,包含寄存器地址和寄存器数据等。

差错校验:对数据进行冗余校验的结果,CRC或LRC。

4.6.2.1Modbus-ASCII

Modbus-ASCII传输模式中,每个字节均以ASCII编码,实际报文中1个字节会以两个ASCII字符发送,因此这种模式比Modbus-RTU模式效率要低。

例如报文数据0x5B="5"+"B"=0X35+0X42。数据帧格式如下:

从ASCII数据帧可以看出,ASCII模式增加了帧起始(“:”)和帧结束标志(回车换行),由于报文数据每个字节在ASCII模式下需要2个字符进行编码,为了保证ASCII模式和RTU模式在应用级兼容,ASCII模式数据块最大长度为252*2,所以可以计算出报文帧最大长度为1+2+2+2x252+2+2=513字符,报文帧内的字符间隔时间可以达1秒钟。

Modbus-ASCII模式校验方法采用的是纵向冗余校验(LRC,LongitudinalRedundancyChecking)算法,校验内容不包括帧起始和帧结束字符。

计算方法也比较简单,对校验内容进行累加和计算,忽略进位,并转换为二进制补码:

例如Modbus-ASCII模式,主机发送请求,向地址为1的从设备的0x405地址,写入数值0x1234,报文如下:

:010604051234AACRLF

即:

:010604051234AACRLF

可以看到01表示设备地址,06表示写单个保持寄存器。地址为0x0405,数据为0x1234,LRC校验值为0xAA。实际进行校验的数据不包含帧头和帧尾。

0xAA=LRC(01,06,04,05,12,34)

手动LRC计算方法:

把原始数据两个字符组成一个字节,并进行二进制加法计算:01+06+04+05+12+34=0x56,计算二进制补码:

0x56=01010110

取反:10101001

加1:10101010=0xAA

或者:0x100-0x56=0xAA

或者可以利用在线工具计算:LRC校验码在线计算器。

4.6.2.2Modbus-RTU

Modbus-RTU数据帧,帧长度最大为256字节,由以下四部分构成:

子节点地址:1字节,范围0-247。

功能代码:1字节。

数据块:0-252字节。

CRC校验值:2字节,低8位在前。

Modbus-RTU帧间隔,Modbus-RTU要求两个RTU报文帧间隔要大于3.5个字节时间:

ModbusRTU帧间隔且每个报文帧内字节间隔小于1.5个字节时间,否则会认为接收不完整。

Modbus-RTU采用循环冗余校验(CRC-CyclicalRedundancyChecking)算法对报文帧全部数据进行计算,得到的校验值附加在报文帧末尾,低位在前。CRC-16_Modbus计算方法可以参考:CRC-16_Modbus校验算法。

也可以用在线工具:16进制(CRC16)(MODBUSRTU通讯)校验码在线计算器计算CRC校验值。

例一:写单个寄存器。向01地址设备0x0105保持寄存器写入1个数据:0x0190

主机发送:01060105019099CB

从机回复:01060105019099CB

其中,01表示从机地址,06功能码表示写单个保持寄存器,0105表示寄存器地址,0190表示写入寄存器的数值,99CB为CRC校验值。可以看出,当写1个寄存器数据时,从机响应的数据帧和主机发送的数据帧完成一致。

例二:写多个寄存器。向01地址设备0x0105、0x0106、0x0107地址保持寄存器,写入3个寄存器数据:0x1102、0x0304、0x0566。

主机发送:011001050003061102030405664a12

从机回复:01100105000391f5

同理,01从机地址,10功能码表示写多个保持寄存器,0105表示起始地址,0003表示写3个寄存器,06表示数据量为6个字节,1102/0304/0566分别表示写入3个寄存器的数值,4a12表示CRC校验数值。

可以看出,写多个寄存器时使用10功能码,从机回复数据也比较精简。

例三:读单个寄存器。读01地址设备0x0105保持寄存器数据。

主机发送:01030105000195f7

从机回复:010302567887c6

主机发送数据中,03表示读多个寄存器,0105表示起始地址,0001表示读1个寄存器。

从机回复值中,02表示2个字节,5678表示寄存器的数据。

例四:读多个寄存器。读01地址设备0x0105、0x0106、0x0107地址保持寄存器,共3个寄存器数据。

主机发送:0103010500031436

从机回复:0103061122334455662a18

03表示读多个寄存器,0105表示起始地址,0003表示读3个寄存器。

06表示6个字节,112233445566表示寄存器的数据。

4.6.2.3Modbus-TCP

Modbus-TCP基于以下种报文类型:

MODBUS请求:客户机在网络上发送用来启动事务处理的报文

MODBUS证实:在客户端接收的响应信息

MODBUS指示:服务端接收的请求报文

MODBUS响应:服务器发送的响应信息

报文头的数据字段代表其用途。首先,它包含一个事务处理标识符。这有助于网络允许同时发生多个未处理的请求。也就是说,主设备可以发送请求1、2和3。在稍后的时间点,从设备能以2、1、3的顺序进行响应,并且主设备可以将请求匹配到响应并准确解析数据。这对于以太网网络来说很有用。

协议标识符通常为零,但您可以使用它来扩展协议的行为。协议使用长度字段来描述数据包其余部分的长度。此元素的位置也表明了这个报文头格式在可靠网络层上的依赖关系。由于TCP数据包具有内置的错误检查功能,并可确保数据一致性和传递,因此数据包长度可位于报文头的任何位置。在可靠性较差的网络上(比如串行网络),数据包可能会丢失,其影响是即使应用程序读取的数据流包含有效的事务处理和协议信息,长度信息的损坏也会使报文头无效。TCP为这种情况提供了适当的保护。

TCP/IP设备通常不使用单元ID。但是,Modbus是一种常见的协议,因此通常会开发许多网关来将Modbus协议转换为其他协议。在最初的预期应用中,ModbusTCP/IP转串行网关用于连接新的TCP/IP网络与旧的串行网络。在这种环境中,单元ID用于确定PDU实际对应的从设备的地址。

最后,ADU还包含一个PDU。对于标准协议,PDU的长度仍限制为253字节。

Modbus协议中主机可以以两种模式对从机设备发出请求:单播和广播。

4.6.2.3.1单播模式

在单播模式下,从机地址必须唯一,地址范围1-247。主机以特定地址访问指定的某个从机,发出一个请求数据帧,这个数据帧功能可以是读取或写入数据,从机接收到并处理完成后,会回报一个应答数据帧,以表示读取或写入成功。

4.6.2.3.2广播模式

在广播模式下,主机向所有的从机发出请求数据帧,所有的从机都会处理这条命令,对于广播请求,所有的从机无需做出应答操作。一般地址0表示广播地址。

五Modbus组件的使用1Gitee链接地址

组件位于amaziot_bloom_os_sdk\libraries\am\xtu\am_

第三方组件位于amaziot_bloom_os_sdk\libraries\third_party\agile_,可以在github上查找相关api文档。

Gitee源码地址:

Github源码地址:

2应用层组件功能介绍

提供Modbus实例。实现轮询。

使用该组件,必须同时使用AT组件,文件组件,TCP组件,掉线组件,掉线重连组件,心跳组件,JSON组件,Modbus组件。

3代码讲解

1dtu_modbus_task_init

初始化modbus任务

voiddtu_modbus_task_init(void){OSA_STATUSstatus=0;/*creatmessage*/status=OSAMsgQCreate(dtu_modbus_msgq,"dtu_modbus_msgq",DTU_MODBUS_TASK_MSGQ_MSG_SIZE,DTU_MODBUS_TASK_MSGQ_QUEUE_SIZE,OS_FIFO);ASSERT(status==OS_SUCCESS);status=OSATaskCreate(dtu_modbus_msgq_task_ref,dtu_modbus_task_stack,DTU_MODBUS_TASK_STACK_SIZE,161,"modbus_task",dtu_modbus_task,NULL);ASSERT(status==OS_SUCCESS);}

2dtu_modbus_task

modbus主任务,接收发送Modbus数据

staticvoiddtu_modbus_task(void*ptr){OSA_STATUSstatus=0;intret=0;inti=0;//intid=0;ints_len=0;DTU_MSG_UART_DATA_PARAM_Tuart_data={0};uint8_tctx_s_buf[AGILE_MODBUS_MAX_ADU_LENGTH];uint8_tctx_read_buf[1];//uint8_ts[100]={0};//uint8_trecv[100]={0};//uint8_t*temp=NULL;DTU_FILE_PARAM_T*dtu_file_ctx=NULL;dtu_file_ctx=dtu_get_file_ctx();agile_modbus_rtu_tctx_dtu={0};agile_modbus_t*ctx=ctx_dtu._ctx;agile_modbus_rtu_init(ctx_dtu,ctx_s_buf,sizeof(ctx_s_buf),ctx_read_buf,sizeof(ctx_read_buf));dtu_modbus_interval_timer_init();st_dtu_=DTU_MODBUS_POOLLING_STATE;if(DTU_MODBUS_TYPE_ENABLE==dtu_file_){dtu_modbus_interval_timer_start();}//defineAGILE_MODBUS_FC_READ_DISCRETE_INPUTS0x02//defineAGILE_MODBUS_FC_READ_INPUT_REGISTERS0x04//defineAGILE_MODBUS_FC_WRITE_SINGLE_REGISTER0x06//defineAGILE_MODBUS_FC_WRITE_MULTIPLE_COILS0x0F//defineAGILE_MODBUS_FC_REPORT_SLAVE_ID0x11//defineAGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS0x17while(1){//阻塞1s等待从机回复的数据status=OSAMsgQRecv(dtu_modbus_msgq,(void*)uart_data,DTU_MODBUS_TASK_MSGQ_MSG_SIZE,OSA_SUSPEND);if(status==OS_SUCCESS){if(DTU_MODBUS_TIMER_INTERVAL_MSG==uart_){//uprintf("%s[%d]timermsg\r\n",__FUNCTION__,__LINE__);if(DTU_MODBUS_POOLLING_STATE==st_dtu_){//for循环查询列表中哪些指令激活,按照激活指令参数配置指令for(i=st_dtu_;iDTU_MODBUS_CMD_NUM;i++){//当前列表第i指令被激活if(DTU_MODBUS_ACTIVE==dtu_file_[i].active){//设置从机地址agile_modbus_set_slave(ctx,dtu_file_[i].slave_addr);uprintf("%s[%d]slaveaddr:%did:%dcmd:0x%02X\n",__FUNCTION__,__LINE__,dtu_file_[i].slave_addr,st_dtu_+1,dtu_file_[i].fn);}else{//uprintf("%s[%d]nonecmdcontinuei:%did:%d\n",__FUNCTION__,__LINE__,i+1,st_dtu_);st_dtu_=i+1;continue;}//根据指令01来组包if(dtu_file_[i].fn==AGILE_MODBUS_FC_READ_COILS){//组包数据s_len=agile_modbus_serialize_read_bits(ctx,dtu_file_[i].reg_addr,dtu_file_[i].reg_n_d);}//根据指令02来组包elseif(dtu_file_[i].fn==AGILE_MODBUS_FC_READ_DISCRETE_INPUTS){//组包数据s_len=agile_modbus_serialize_read_input_bits(ctx,dtu_file_[i].reg_addr,dtu_file_[i].reg_n_d);}//根据指令03来组包elseif(dtu_file_[i].fn==AGILE_MODBUS_FC_READ_HOLDING_REGISTERS){//组包数据s_len=agile_modbus_serialize_read_registers(ctx,dtu_file_[i].reg_addr,dtu_file_[i].reg_n_d);}//根据指令04来组包elseif(dtu_file_[i].fn==AGILE_MODBUS_FC_READ_INPUT_REGISTERS){//组包数据s_len=agile_modbus_serialize_read_input_registers(ctx,dtu_file_[i].reg_addr,dtu_file_[i].reg_n_d);}//根据指令05来组包elseif(dtu_file_[i].fn==AGILE_MODBUS_FC_WRITE_SINGLE_COIL){//组包数据s_len=agile_modbus_serialize_write_bit(ctx,dtu_file_[i].reg_addr,dtu_file_[i].reg_n_d);}//根据指令06来组包elseif(dtu_file_[i].fn==AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER){//组包数据s_len=agile_modbus_serialize_write_register(ctx,dtu_file_[i].reg_addr,dtu_file_[i].reg_n_d);}//uprintf("%s[%d]findcmd\r\n",__FUNCTION__,__LINE__);//当前激活id,跳出这次循环break;}st_dtu_++;//uprintf("%s[%d]sbuflen:%dmdid:%d\r\n",__FUNCTION__,__LINE__,s_len,st_dtu_);if(st_dtu__MODBUS_CMD_NUM){st_dtu_=0;st_dtu_=DTU_MODBUS_POOLLING_WN_STATE;uprintf("%s[%d]poolling",__FUNCTION__,__LINE__);//停止modbus驱动定时器//dtu_modbus_interval_timer_stop();//轮训完毕后,重新开始之前等待时间//dtu_sleep(dtu_file_);//开始modbus驱动定时器//dtu_modbus_interval_timer_start();}else{//uprintf("%s[%d]smdhex\r\n",__FUNCTION__,__LINE__);//intj=0;//for(j=0;js_len;j++)//{//uprintf("regdata[%d]:%X\r\n",j,ctx-s_buf[j]);//}//发送数据到串口UART_SEND_DATA(ctx-s_buf,s_len);}}elseif(DTU_MODBUS_POOLLING_WN_STATE==st_dtu_){//for循环查询列表中哪些指令激活,按照激活指令参数配置指令for(i=st_dtu_;iDTU_MODBUS_CMD_WN_NUM;i++){//当前列表第i指令被激活if(DTU_MODBUS_ACTIVE==dtu_file__wn[i].active){//设置从机地址agile_modbus_set_slave(ctx,dtu_file__wn[i].slave_addr);uprintf("%s[%d]slaveaddr:%did:%dcmd:0x%02X",__FUNCTION__,__LINE__,dtu_file__wn[i].slave_addr,st_dtu_+1,dtu_file__wn[i].fn);}else{//uprintf("%s[%d]nonecmdcontinuei:%did:%d\n",__FUNCTION__,__LINE__,i+1,st_dtu_);st_dtu_=i+1;continue;}//根据指令0F来组包//if(dtu_file__wn[i].fn==AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS)//{//uprintf("cmd0x10regnum:%d\r\n",dtu_file__wn[i].reg_n_d);//组包数据//s_len=agile_modbus_serialize_write_registers(ctx,dtu_file__wn[i].reg_addr,dtu_file__wn[i].reg_n,(UINT16*)dtu_file__wn[i].reg_data);//intj=0;//for(j=0;jdtu_file__wn[i].reg_n_d;j++)//{//uprintf("regdata[%d]:%X\r\n",j,dtu_file__wn[i].reg_data[j]);//}//}//根据指令10来组包if(dtu_file__wn[i].fn==AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS){//uprintf("cmd0x10regnum:%d\r\n",dtu_file__wn[i].reg_n_d);//组包数据s_len=agile_modbus_serialize_write_registers(ctx,dtu_file__wn[i].reg_addr,dtu_file__wn[i].reg_n,(UINT16*)dtu_file__wn[i].reg_data);//intj=0;//for(j=0;jdtu_file__wn[i].reg_n_d;j++)//{//uprintf("regdata[%d]:%X\r\n",j,dtu_file__wn[i].reg_data[j]);//}}//uprintf("%s[%d]findcmd\r\n",__FUNCTION__,__LINE__);//当前激活id,跳出这次循环break;}st_dtu_++;//uprintf("%s[%d]sbuflen:%dmdid:%d\r\n",__FUNCTION__,__LINE__,s_len,st_dtu_);if(st_dtu__MODBUS_CMD_WN_NUM){st_dtu_=0;st_dtu_=DTU_MODBUS_POOLLING_STATE;uprintf("%s[%d]wnpoolling",__FUNCTION__,__LINE__);//停止modbus驱动定时器dtu_modbus_interval_timer_stop();//轮训完毕后,重新开始之前等待时间dtu_sleep(dtu_file_);//开始modbus驱动定时器dtu_modbus_interval_timer_start();}else{//uprintf("%s[%d]smdhex\r\n",__FUNCTION__,__LINE__);//intj=0;//for(j=0;js_len;j++)//{//uprintf("regdata[%d]:%X\r\n",j,ctx-s_buf[j]);//}//发送数据到串口UART_SEND_DATA(ctx-s_buf,s_len);}}}elseif(DTU_MODBUS_DATA_MSG==uart_!=uart_){//uprintf("%s[%d]modbusres",__FUNCTION__,__LINE__);////UINT8*p=uart_;//for(i=0;iuart_;i++)//{//uprintf("0x%02X",p[i]);//}//如果是modbus数据,判断目前是modbusrtu上报模式,modbustcp上报模式,还是json上报格式if(DTU_MODBUS_RESPONSE_JSON_TYPE==dtu_file__type){uprintf("modbusjsonres");dtu_modbus_json_modbus_res(uart_,uart_);}//elseif(DTU_MODBUS_RESPONSE_TCP_TYPE==dtu_file__type)//{////判断是否是modbus一帧数据//ret=dtu_modbus_protocol_check(uart_,uart_);//if(DTU_MODBUS_PROTOCOL_SUCCESS==ret)//{//uprintf("modbustcpres");//}//}else{uprintf("modbusrtures");//modbusrtu帧,直接发if/*ifdefDTU_BASED_ON_:01:18by:zhaoning*/if/*ifdefDTU_BASED_ON_:01:28by:zhaoning*/}//释放数据内存free(uart_);//置空uart_=NULL;}}}}

3dtu_modbus_interval_timer_init

初始化指令间隔定时器,Modbus轮询过程中每个指令之间的间隔时间

staticvoiddtu_modbus_interval_timer_init(void){OSA_STATUSstatus=0;//初始化指令间隔定时器status=OSATimerCreate(st_dtu__timer_ref);ASSERT(status==OS_SUCCESS);}

4dtu_modbus_interval_timer_start

开始指令间隔定时器

voiddtu_modbus_interval_timer_start(void){DTU_FILE_PARAM_T*dtu_file_ctx=NULL;dtu_file_ctx=dtu_get_file_ctx();OSATimerStart(st_dtu__timer_ref,dtu_file_*200,dtu_file_*200,dtu_modbus_interval_timer_callback,0);}
4Demo实战4.1创建一个Demo

复制20.9_di_xtu示例工程,到同一个文件夹下,修改文件名为20.12_json_xtu,如图:

4.2修改makefile

增加文件组件所在目录头文件路径,和源文件路径,以及一些宏定义,如图:

-D是makefile中定义宏定义必要的前缀,可以搜索相关makefile学习文章学习相关知识。

DTU_BASED_ON_TCP表示当前是TCP模式,当前组件使用需要中包含一些对应。

DTU_TYPE_5X6表示使用SOM板贴片5x6卡,可以使用其它卡,修改为对应宏定义就可以。

DTU_UART_115200_BAUD表示使用115200波特率

DTU_TYPE_JSON_INCLUDE表示把JSON功能包含进来

4.3增加头文件

使用代码编辑器,将新建的工程文件加入代码编辑器中,打开,修改,加入头文件,如图:

4.4修改代码

示例使用的是板载5x6卡,用户的硬件可能是使用外置卡,或者是三合一全网通卡,因为硬件上三种卡使用的模组SIM卡接口不一样(外置卡SIM1,5x6卡和三合一卡SIM2),所以,需要通过一个全局变量来制定SIM卡硬件接口。

extern外部变量SDK_INIT_SIM_SELECT_VALUE,这里判断了是否使用外置卡,这个宏定义在Makefile里面定义。

在Phase1Inits_enter中,宏定义判断是否要包含对SDK_INIT_SIM_SELECT_VALUE变量的修改。

在Phase2Inits_exit调用文件组件提供的对外API,如图:

4.5编译

在SDK根目录打开命令行,输入命令.\\amaziot_bloom_os_sdk\sample\libraries\20.14_modbus_xtu\

PSF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08λ.\\amaziot_bloom_os_sdk\sample\libraries\20.14_modbus_xtu\子目录或文件out\bin已经存在。子目录或文件build\cJSON已经存在。子目录或文件build\obj已经存在。gnumake:Enteringdirectory`F:/3.asr-b//1.software/BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/sample/libraries/20.14_modbus_xtu'_unaligned_access-g-O2--apcs/inter--diag_suppress2084,1,2,177,188,223,550,1296,2795,6319,9931,9933--diag_error=warning--gnu--thumb--loose_implicit_cast-DDATA_COLLECTOR_IMPL-DISPT_OVER_SSP-DDIAG_SSP_DOUBLE_BUFFER_USE_DYNAMIC_ALLOCATION-DENV_XSCALE-DL1_DCXO_ENABLED-DLTE_HIGH_MOBILITY_OPTIMIZATION-DRUN_XIP_MODE-DCRANE_Z2-DCA_LONG_IPC_MSG-DNEZHA3-DNEZHA3_1826-DUPGRADE_PLMS-DUPGRADE_PLMS_SR-DLTE_GSMMULTIBCCH-DGPLC_LTE_RSSI_SCAN-DL1V_NEW_RSSI-DUPGRADE_PLMS_3G-DUPGRADE_PLMS_L1-DUPGRADE_FG_PLMS-DFG_PLMS_URR-DUPGRADE_L1A_FG_PLMS-DUPGRADE_PLMS_STAGE_2-DUPGRADE_MBCCH-DMULTI_BCCH_READY_IND-DURR_MRAT_ICS_SEARCH-DUPGRADE_ICS-DMRAT_NAS-DUPGRADE_PLMS_SEARCH_API-DICS_MBCCH-DICS_MBCCH_2G_RSSI-DDIAG_NEWPP-DPHS_SW_DEMO-DPHS_SW_DEMO_TTC-DPHS_SW_DEMO_TTC_PM-DFULL_SYSTEM-D_DDR_INIT_-D_TAVOR_HARBELL_-DUPGRADE_ARBEL_PLATFORM-D_TAVOR_B0_SILICON_-DTDL1C_SPY_ENABLE-DDLM_TAVOR-DTAVOR-DFLAVOR_DUALCORE-DDEBUG_D2_MOR_REG_RESEREVED_ENABLE-D_DIAG_USE_COMMSTACK_-D_TAVOR_DIAG_-DPM_DEBUG_MODE_ENABLED-DPM_D2FULL_MODE-DPM_EXT_DBG_INT_ARR-DFEATURE_WB_AMR_PS-DMACRO_FOR_LWG-DHL_LWG-DOPTIMIZE_FOR_2G_BCCH-DPLAT_TEST-D_FDI_USE_OSA_-DPLAT_USE_THREADX-DLWIP_IPNETBUF_SUPPORT-DCRANE_MCU_DONGLE-DAT_OVER_UART-DPHS_SW_DEMO_TTC_PM-DUPGRADE_LTE_ONLY-DEXT_AT_MODEM_SUPPORT-DLTEONLY_THIN_SINGLE_SIM-DLFS_FILE_SYS-DLFS_FILE_SYS_V2-DPSM_ENABLE-DNO_PAHO_MQTT-DNO_XML-DNO_LWM2M-DREMOVE_MBEDTLS-DNO_AT_NET-DCRANE_SD_NOT_SUPPORT-DNTP-DYMODEM_EEH_DUMP-DENABLE_DM_LTEONLY-DLTEONLY_THIN-DNO_EXTEND_MY_Q_AT-DNOT_SUPPORT_HTTPS-DNOT_SUPPORT_PM813-DCRANEL_4MRAM-DREMOVE_PB-DUART_NEW_VERSION-DREMOVE_MEP-DREMOVE_SMS-DREMOVE_ENVSIM-DAPN_INCODE-DLTEONLY_THIN_SINGLE_SIM_2MFLASH-DASR160X_OPENCPU_FEATURE-DENABLE_UART3_FEATRUE-DENABLE_UART4_FEATRUE-DYUGE_MBEDTLS_3_2_1-DENABLE_MAC_TX_DATA_LOGGING-DDISABLE_NVRAM_ACCESS-DINTEL_UPGRADE_EE_HANDLER_SUPPORT-DLTE_W_PS-DL1_DUAL_MODE-DUPGRADE_HERMON_DUAL-DINTEL_UPGRADE_DUAL_RAT-DINTEL_UPGRADE_GPRS_CIPHER_FLUSH-DUPGRADE_ENHANCED_QUAD_BAND-DINTEL_2CHIP_PLAT-DI_2CHIP_PLAT-DUPGRDE_TAVOR_COMMUNICATION-DRUN_WIRELESS_MODEM-DFLAVOR_DDR12MB_GB1MB5-DFEATURE_SHMEM-DACIPC_ENABLE_NEW_CALLBACK_MECHANISM-DRELIABLE_DATA-DMAP_NSS-DTV_FNAME="\"SW_PLATFORM=PMD2NONEPHS_SW_DEMOPHS_SW_DEMO_PMSRCNUCLEUSFULL_SYSTEMNOACRTCPDFLTPLAT_TESTPV2DIAGOSHMEMNVMWITHL1V\""-DTV_FDESC="\"SW_DESCRIPTION=\""-DENABLE_ACIPC-D_DATAOMSL_ENABLED_-DUSB_CABLE_DETECTION_VIA_PMIC-DMIPS_TEST-DMIPS_TEST_RAM-DFLAVOR_DIET_RAM-DNVM_INCLUDE-DMSL_INCLUDE-DMSL_POOL_MEM-DNO_AUDIO-DOSA_QUEUE_NAMES-D_DIAG_DISABLE_USB_-DOSA_NUCLEUS-DOSA_USED-DPM_D2NONE_MODE-DCRANE_SOC_TEMPERATURE_SENSOR-DL1_SW_UPDATE_FOR_DIGRF-DPHS_L1_SW_UPDATE_R7-DUPGRADE_LTE-DFRBD_CALIB_NVM-DFRBD_AGC_CALIB-DFRBD_FDT_CALIB-DHSPA_MPR-DCAPT_PARAMS_OPTIMIZE-DL1_WB_R99_ONLY-DL1V_WB_R99_ONLY-DINTERGRATED_RF_SUPPORT-DL1_RX_DIV_SUPPORT-DENABLE_OOS_HANDLING-DTAVOR_D2_WB_L1_SUPPORT-DL1_DDR_HIGH_FREQ-DUPGRADE_DIGRF3G_SUPPORT-DW_PS_PLUS_G_PAGING-D"NO_APLP=0"-DINTEL_UPGRADE_UNIFIED_VOICE_TASK-DINTEL_UPGRADE_R99-DAPLP_SPY_ENABLE-D__TARGET_FEATURE_DOUBLEWORD-DWHOLE_UMTS_STACK-DUSE_TTPCOM_CSR_BLUETOOTH_AUDIO_GAIN_CONTROL-DL1_UPGRADE_R5-DUPGRADE_EDGE-DUPGRADE_R4_FS1-DINTEL_UPGRADE_GSM_CRL_IF-DUPGRADE_EGPRS_M-DINTEL_UPGRADE_EGPRS_M-DINTEL_UPGRADE_RF_PARAMS_IN_CF_TDS-DINTEL_UPGRADE_2SAMPLES_PER_SYMBOL-D"GPRS_MULTISLOT_CLASS=12"-D"EGPRS_MULTISLOT_CLASS=12"-DMARVELL_UPGRADE_BSIC_REDESIGN-DMSL_INCLUDE-DINTEL_HERMON_SAC-DCRANE_CUST_BUILD-DL1_SW_UPDATE_FOR_DIGRF-DFLAVOR_COM-DSILICON_PV2-DSILICON_SEAGULL-DSILICON_TTC_CORE_SEAGULL-DPCAC_INCLUDE-Otime-DBUILD_DATE="\"11222023\""-DBUILD_TIME="\"11:19:00\""-Iatcmds\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\telephony\yuge\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\UART\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\core\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\PMU\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\GPIO\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\os\posix\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\diag\diag_logic\src-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\csw\SysCfg\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\csw\platform\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\env\win32\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\csw\BSP\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\csw\platform\dev_plat\build-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\os\osa\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\os\threadx\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\os\nu_xscale\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\psm\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\httpclient\src-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\diag\diag_logic\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\timer\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\intc\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\csw\PM\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\pm\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\TickManager\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\BSP\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\telephony\atcmdsrv\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\telephony\atparser\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\telephony\sdk\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\httpclient\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\ci\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\lwipv4v6\src\include-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\lwipv4v6\src\include\arch-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\lwipv4v6\src\include\ipv4-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\lwipv4v6\src\include\ipv6-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\lwipv4v6\src\include\lwip-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\lwipv4v6\src\include\netif-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\mmi_mat\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\tavor\Arbel\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\tavor\env\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\telephony\modem\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\duster\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\fota\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\I2C\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\ACIPC\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\fatsys\flash-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\FDI\src\INCLUDE-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\MMU\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\FDI\src\FDI_ADD-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\FDI\src\FM_INC-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\fatsys\fs\hdr-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\littlefs\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\tts\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\dial\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\csw_memory\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\utilities\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\commpm\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\nvm\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\EEhandler\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\EEhandler\src-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\RTC\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\telephony\ci_client\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\BT_device\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\UART\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\mrd\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\dma\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\softutil\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\SPI\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\websocket\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\atnet_srv\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\softutil\fotacomm\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\aud_sw\Audio\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\aud_sw\ACM_COMM\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\aud_sw\audio_stub\src-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hop\aam\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\aud_sw\AudioHAL\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\hal\dbgshell\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\include\asr160x\pcac\opencpu\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\amaziot_bloom_os_sdk\utils-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\CSDK_CODE\cJSON\inc-IF:/3.asr-b//1.software/BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/sample/libraries/20.14_modbus_xtu\am\inc-IF:/3.asr-b//1.software/BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/sample/libraries/20.14_modbus_xtu\atcmds\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/libraries\am\xtu-DDTU_BASED_ON_TCP-DDTU_TYPE_5X6-DDTU_UART_115200_BAUD-DDTU_TYPE_MODBUS_INCLUDE-DDTU_TYPE_JSON_INCLUDE-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/libraries/third_party/agile_\inc-IF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/libraries/third_party/agile_\util-obuild\obj/ext_at_:/3.asr-b//1.software/BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/sample/libraries/20.14_modbus_xtu/atcmds/src/ext_at_\obj/\obj/ext_at_\obj/ext_at_\obj/am_\obj/am_\obj/am_\obj/am_\obj/am_\obj/am_\obj/am_\obj/am_\obj/utils_\obj/agile_modbus_slave_\obj/agile_\obj/agile_modbus_\obj/agile_modbus_\CSDK_\-oF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\out\bin\Arbel_PMD2NONE_40\--viaF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\prebuilt_1606l\Arbel_PMD2NONE_targ_\--elf\--scatterF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\prebuilt_1606l\Crane_DS_4M_Ram_2M_Flash_XIP_CIPSRAM_Common_\--predefine="-DLTEONLY_THIN_SINGLE_SIM"--map--symbols--infosizes,totals\--listF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\out\bin\Arbel_PMD2NONE_40\--(Header)--(Vectors)--diag_suppress6312,6314,6319,6329\--feedbackF:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\out\feedbackLinkOptLteonlyThin_SingleSim_:\3.asr-b\\1.software\BLOOM_OS_1606_OPENCPU_1191_A08\tools\buildimage_1606_PROD_TYPE:[DM]SDK_CUST_SKU:[THIN_SINGLE_SIM_NO_SMS]SDK_PS_MODE:[LTEONLY]SDK_CHIP_VER:[Z2A0]SDK_OS_TYPE:[TX]!|INPUT|out\bin\cp_1606|MARK|NAME||COMPRESSSTASTIC||--------|--------|--------.--------.--------.--------|------------------------------||ThisIsLteOnly4M||RW_CPZ_1|DDR_RW_|7|0000d290-00003000|ThisIsLteOnly4M||RW_CPZ_2|PS_NCAH|7|00001300-00001000|ThisIsLteOnly4M||RW_CPZ_3|ITCM|7|0000f51c-0000a000|ThisIsLteOnly4M||RW_CPZ_4|CODE_PS|7|0002fcdc-0001e000|ThisIsLteOnly4M||RW_CPZ_5|CODEPSB|7|000339bc-0001b000|ThisIsLteOnly4M||RW_CPZ_6|CODEPSC|7|000323ec-0001b000|ThisIsLteOnly4M||RW_CPZ_7|CODEPSD|7|00028d88-0001a000|ThisIsLteOnly4M||RW_CPZ_8|CODEPSE|7|0002e310-0001a000|ThisIsLteOnly4M||RW_CPZ_9|CODEPSF|7|0001c948-00011000|ThisIsLteOnly4M||RW_CPZ_A|CODE_PL|7|0002f914-0001e000|ThisIsLteOnly4M||RW_CPZ_B|CODEPLB|7|00038d38-00021000|ThisIsLteOnly4M||RW_CPZ_C|CODEPLC|7|000268d4-00012000|--------|--------|--------.--------.--------.--------|------------------------------|||0x0020a6d4-0x0014d000|||2.041(MB)-1.301(MB)||------------------------------------------------------------------------------------|cp_1606_1606_1606:Leavingdirectory`F:/3.asr-b//1.software/BLOOM_OS_1606_OPENCPU_1191_A08/amaziot_bloom_os_sdk/sample/libraries/20.14_modbus_xtu'"copyNEZHAC_CP_CNR_MIFI_/"已复制1个文件。
4.6生成固件

参考入门中开发工具,生成工具。

4.7查看现象

固件下载到模组后,配置服务器地址,配置Modubs指令,之后用Modbus客户端来模拟查看

[11-2211:46:54:993][11-2211:46:54:993]OK[11-2211:46:56:212][11-2211:46:56:212]AT+TRANSIP="TCP","101.200.35.208",8866[11-2211:46:56:212][11-2211:46:56:212]OK[11-2211:46:58:042][11-2211:46:58:042]CONNECTOK[11-2211:46:59:123][11-2211:46:59:123]AT+MBADD=1,1,1,1,0,10[11-2211:46:59:123][11-2211:46:59:123]OK[11-2211:46:59:515][11-2211:46:59:515]AT+MBADD=2,1,1,2,0,10[11-2211:46:59:515][11-2211:46:59:515]OK[11-2211:47:00:287][11-2211:47:00:287]AT+MBADD=3,1,1,3,0,10[11-2211:47:00:287][11-2211:47:00:287]OK[11-2211:47:00:709][11-2211:47:00:709]AT+MBADD=20,1,1,4,0,10[11-2211:47:00:709][11-2211:47:00:709]OK[11-2211:47:01:172][11-2211:47:01:172]AT+MBADD=49,1,1,5,0,10[11-2211:47:01:172][11-2211:47:01:172]OK[11-2211:47:01:669][11-2211:47:01:669]AT+MBADD=50,1,1,6,0,6666[11-2211:47:01:669][11-2211:47:01:669]OK[11-2211:47:02:336][11-2211:47:02:336]AT+MBADDWN=1,1,1,16,0,5,"16B352A9F615D7D3FE198"[11-2211:47:02:336][11-2211:47:02:336]OK[11-2211:47:02:937][11-2211:47:02:937]AT+MBCFG=1,1,3,6[11-2211:47:02:937][11-2211:47:02:937]OK

5总结

根据实验现象,用户需要实现自己的AT指令,只需要参考组件中的例子,按照自己需求修改,