394 lines
41 KiB
HTML
394 lines
41 KiB
HTML
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|||
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
|
<head>
|
|||
|
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
|||
|
|
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
|
|||
|
|
<meta name="generator" content="Doxygen 1.9.2"/>
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|||
|
|
<title>Agile Modbus: Agile Modbus</title>
|
|||
|
|
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
|||
|
|
<script type="text/javascript" src="jquery.js"></script>
|
|||
|
|
<script type="text/javascript" src="dynsections.js"></script>
|
|||
|
|
<link href="navtree.css" rel="stylesheet" type="text/css"/>
|
|||
|
|
<script type="text/javascript" src="resize.js"></script>
|
|||
|
|
<script type="text/javascript" src="navtreedata.js"></script>
|
|||
|
|
<script type="text/javascript" src="navtree.js"></script>
|
|||
|
|
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
|||
|
|
<script type="text/javascript" src="search/searchdata.js"></script>
|
|||
|
|
<script type="text/javascript" src="search/search.js"></script>
|
|||
|
|
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
|||
|
|
<div id="titlearea">
|
|||
|
|
<table cellspacing="0" cellpadding="0">
|
|||
|
|
<tbody>
|
|||
|
|
<tr style="height: 56px;">
|
|||
|
|
<td id="projectalign" style="padding-left: 0.5em;">
|
|||
|
|
<div id="projectname">Agile Modbus<span id="projectnumber"> 1.1.2</span>
|
|||
|
|
</div>
|
|||
|
|
<div id="projectbrief">Lightweight modbus protocol stack.</div>
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
<!-- end header part -->
|
|||
|
|
<!-- 制作者 Doxygen 1.9.2 -->
|
|||
|
|
<script type="text/javascript">
|
|||
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|||
|
|
var searchBox = new SearchBox("searchBox", "search",'搜索','.html');
|
|||
|
|
/* @license-end */
|
|||
|
|
</script>
|
|||
|
|
<script type="text/javascript" src="menudata.js"></script>
|
|||
|
|
<script type="text/javascript" src="menu.js"></script>
|
|||
|
|
<script type="text/javascript">
|
|||
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|||
|
|
$(function() {
|
|||
|
|
initMenu('',true,false,'search.php','搜索');
|
|||
|
|
$(document).ready(function() { init_search(); });
|
|||
|
|
});
|
|||
|
|
/* @license-end */
|
|||
|
|
</script>
|
|||
|
|
<div id="main-nav"></div>
|
|||
|
|
</div><!-- top -->
|
|||
|
|
<div id="side-nav" class="ui-resizable side-nav-resizable">
|
|||
|
|
<div id="nav-tree">
|
|||
|
|
<div id="nav-tree-contents">
|
|||
|
|
<div id="nav-sync" class="sync"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div id="splitbar" style="-moz-user-select:none;"
|
|||
|
|
class="ui-resizable-handle">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<script type="text/javascript">
|
|||
|
|
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT */
|
|||
|
|
$(document).ready(function(){initNavTree('index.html',''); initResizable(); });
|
|||
|
|
/* @license-end */
|
|||
|
|
</script>
|
|||
|
|
<div id="doc-content">
|
|||
|
|
<!-- window showing the filter options -->
|
|||
|
|
<div id="MSearchSelectWindow"
|
|||
|
|
onmouseover="return searchBox.OnSearchSelectShow()"
|
|||
|
|
onmouseout="return searchBox.OnSearchSelectHide()"
|
|||
|
|
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- iframe showing the search results (closed by default) -->
|
|||
|
|
<div id="MSearchResultsWindow">
|
|||
|
|
<iframe src="javascript:void(0)" frameborder="0"
|
|||
|
|
name="MSearchResults" id="MSearchResults">
|
|||
|
|
</iframe>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div><div class="header">
|
|||
|
|
<div class="headertitle"><div class="title">Agile Modbus </div></div>
|
|||
|
|
</div><!--header-->
|
|||
|
|
<div class="contents">
|
|||
|
|
<div class="textblock"><p ><a class="anchor" id="md_C__Users_25440_Desktop_stm32f407_atk_explorer_packages_agile_modbus_README"></a> </p>
|
|||
|
|
<h1><a class="anchor" id="autotoc_md18"></a>
|
|||
|
|
1、介绍</h1>
|
|||
|
|
<p >Agile Modbus 即:轻量型 modbus 协议栈,满足用户任何场景下的使用需求。</p>
|
|||
|
|
<p ><img src="./figures/ModbusProtocol.jpg" alt="ModbusProtocol" class="inline"/></p>
|
|||
|
|
<ul>
|
|||
|
|
<li><code>examples</code> 文件夹提供 PC 上的示例</li>
|
|||
|
|
<li>MCU 上的示例查看 <a href="https://github.com/loogg/agile_modbus_mcu_demos">mcu_demos</a></li>
|
|||
|
|
<li>在 AT32F437 上基于 RT-Thread 实现的支持 Modbus 固件升级的 Bootloader:<a href="https://github.com/loogg/AT32F437_Boot">AT32F437_Boot</a></li>
|
|||
|
|
<li>在 HPM6750 上基于 RT-Thread 实现的支持 Modbus 固件升级的 Bootloader:<a href="https://github.com/loogg/HPM6750_Boot">HPM6750_Boot</a></li>
|
|||
|
|
</ul>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md19"></a>
|
|||
|
|
1.1、特性</h2>
|
|||
|
|
<ol type="1">
|
|||
|
|
<li>支持 rtu 及 tcp 协议,使用纯 C 开发,不涉及任何硬件接口,可在任何形式的硬件上直接使用。</li>
|
|||
|
|
<li>由于其使用纯 C 开发、不涉及硬件,完全可以在串口上跑 tcp 协议,在网络上跑 rtu 协议。</li>
|
|||
|
|
<li>支持符合 modbus 格式的自定义协议。</li>
|
|||
|
|
<li>同时支持多主机和多从机。</li>
|
|||
|
|
<li>使用简单,只需要将 rtu 或 tcp 句柄初始化好后,调用相应 API 进行组包和解包即可。</li>
|
|||
|
|
</ol>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md20"></a>
|
|||
|
|
1.2、目录结构</h2>
|
|||
|
|
<table class="markdownTable">
|
|||
|
|
<tr class="markdownTableHead">
|
|||
|
|
<th class="markdownTableHeadNone">名称 </th><th class="markdownTableHeadNone">说明 </th></tr>
|
|||
|
|
<tr class="markdownTableRowOdd">
|
|||
|
|
<td class="markdownTableBodyNone">doc </td><td class="markdownTableBodyNone">文档 </td></tr>
|
|||
|
|
<tr class="markdownTableRowEven">
|
|||
|
|
<td class="markdownTableBodyNone">examples </td><td class="markdownTableBodyNone">例子 </td></tr>
|
|||
|
|
<tr class="markdownTableRowOdd">
|
|||
|
|
<td class="markdownTableBodyNone">figures </td><td class="markdownTableBodyNone">素材 </td></tr>
|
|||
|
|
<tr class="markdownTableRowEven">
|
|||
|
|
<td class="markdownTableBodyNone">inc </td><td class="markdownTableBodyNone">头文件 </td></tr>
|
|||
|
|
<tr class="markdownTableRowOdd">
|
|||
|
|
<td class="markdownTableBodyNone">src </td><td class="markdownTableBodyNone">源代码 </td></tr>
|
|||
|
|
<tr class="markdownTableRowEven">
|
|||
|
|
<td class="markdownTableBodyNone">util </td><td class="markdownTableBodyNone">提供简单实用的组件 </td></tr>
|
|||
|
|
</table>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md21"></a>
|
|||
|
|
1.3、许可证</h2>
|
|||
|
|
<p >Agile Modbus 遵循 <code>Apache-2.0</code> 许可,详见 <code>LICENSE</code> 文件。</p>
|
|||
|
|
<h1><a class="anchor" id="autotoc_md22"></a>
|
|||
|
|
2、使用 Agile Modbus</h1>
|
|||
|
|
<p >帮助文档请查看 <a href="./doc/doxygen/Agile_Modbus.chm">doc/doxygen/Agile_Modbus.chm</a></p>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md23"></a>
|
|||
|
|
2.1、移植</h2>
|
|||
|
|
<ul>
|
|||
|
|
<li><p class="startli">用户需要实现硬件接口的 <code>发送数据</code> 、 <code>等待数据接收结束</code> 、 <code>清空接收缓存</code> 函数</p>
|
|||
|
|
<p class="startli">对于 <code>等待数据接收结束</code>,提供如下几点思路:</p><ol type="1">
|
|||
|
|
<li><p class="startli">通用方法</p>
|
|||
|
|
<p class="startli">每隔 20 / 50 ms (该时间可根据波特率和硬件设置,这里只是给了参考值) 从硬件接口读取数据存放到缓冲区中并更新偏移,直到读取不到或缓冲区满,退出读取。</p>
|
|||
|
|
<p class="startli">这对于裸机或操作系统都适用,操作系统可通过 <code>select</code> 或 <code>信号量</code> 方式完成阻塞。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">串口 <code>DMA + IDLE</code> 中断方式</p>
|
|||
|
|
<p class="startli">配置 <code>DMA + IDLE</code> 中断,在中断中使能标志,应用程序中判断该标志是否置位即可。</p>
|
|||
|
|
<p class="startli">但该方案容易出问题,数据字节间稍微错开一点时间就不是一帧了。推荐第一种方案。</p>
|
|||
|
|
</li>
|
|||
|
|
</ol>
|
|||
|
|
</li>
|
|||
|
|
<li>主机:<ol type="1">
|
|||
|
|
<li><code>agile_modbus_rtu_init</code> / <code>agile_modbus_tcp_init</code> 初始化 <code>RTU/TCP</code> 环境</li>
|
|||
|
|
<li><code>agile_modbus_set_slave</code> 设置从机地址</li>
|
|||
|
|
<li><code>清空接收缓存</code></li>
|
|||
|
|
<li><code>agile_modbus_serialize_xxx</code> 打包请求数据</li>
|
|||
|
|
<li><code>发送数据</code></li>
|
|||
|
|
<li><code>等待数据接收结束</code></li>
|
|||
|
|
<li><code>agile_modbus_deserialize_xxx</code> 解析响应数据</li>
|
|||
|
|
<li>用户处理得到的数据</li>
|
|||
|
|
</ol>
|
|||
|
|
</li>
|
|||
|
|
<li>从机:<ol type="1">
|
|||
|
|
<li>实现 <code>agile_modbus_slave_callback_t</code> 类型回调函数</li>
|
|||
|
|
<li><code>agile_modbus_rtu_init</code> / <code>agile_modbus_tcp_init</code> 初始化 <code>RTU/TCP</code> 环境</li>
|
|||
|
|
<li><code>agile_modbus_set_slave</code> 设置从机地址</li>
|
|||
|
|
<li><code>等待数据接收结束</code></li>
|
|||
|
|
<li><code>agile_modbus_slave_handle</code> 处理请求数据</li>
|
|||
|
|
<li><code>清空接收缓存</code> (可选)</li>
|
|||
|
|
<li><code>发送数据</code></li>
|
|||
|
|
</ol>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">特殊功能码</p>
|
|||
|
|
<p class="startli">需要调用 <code>agile_modbus_set_compute_meta_length_after_function_cb</code> 和 <code>agile_modbus_set_compute_data_length_after_meta_cb</code> API 设置特殊功能码在主从模式下处理的回调。</p><ul>
|
|||
|
|
<li><p class="startli"><code>agile_modbus_set_compute_meta_length_after_function_cb</code></p>
|
|||
|
|
<p class="startli"><code>msg_type == AGILE_MODBUS_MSG_INDICATION</code>: 返回主机请求报文的数据元长度(uint8_t 类型),不是特殊功能码必须返回 0。</p>
|
|||
|
|
<p class="startli"><code>msg_type == MSG_CONFIRMATION</code>: 返回从机响应报文的数据元长度(uint8_t 类型),不是特殊功能码必须返回 1。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code>agile_modbus_set_compute_data_length_after_meta_cb</code></p>
|
|||
|
|
<p class="startli"><code>msg_type == AGILE_MODBUS_MSG_INDICATION</code>: 返回主机请求报文数据元之后的数据长度,不是特殊功能码必须返回 0。</p>
|
|||
|
|
<p class="startli"><code>msg_type == MSG_CONFIRMATION</code>: 返回从机响应报文数据元之后的数据长度,不是特殊功能码必须返回 0。</p>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code>agile_modbus_rtu_init</code> / <code>agile_modbus_tcp_init</code></p>
|
|||
|
|
<p class="startli">初始化 <code>RTU/TCP</code> 环境时需要用户传入 <code>发送缓冲区</code> 和 <code>接收缓冲区</code>,建议这两个缓冲区大小都为 <code>AGILE_MODBUS_MAX_ADU_LENGTH</code> (260) 字节。<code>特殊功能码</code> 情况用户根据协议自行决定。</p>
|
|||
|
|
<p class="startli">但对于小内存 MCU,这两个缓冲区也可以设置小,所有 API 都会对缓冲区大小进行判断:</p>
|
|||
|
|
<p class="startli">发送缓冲区设置:如果 <code>预期请求的数据长度</code> 或 <code>预期响应的数据长度</code> 大于 <code>设置的发送缓冲区大小</code>,返回异常。</p>
|
|||
|
|
<p class="startli">接收缓冲区设置:如果 <code>主机请求的报文长度</code> 大于 <code>设置的接收缓冲区大小</code>,返回异常。这个是合理的,小内存 MCU 做从机肯定是需要对某些功能码做限制的。</p>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md24"></a>
|
|||
|
|
2.2、主机</h2>
|
|||
|
|
<p >见 <code>2.1、移植</code>。</p>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md25"></a>
|
|||
|
|
2.3、从机</h2>
|
|||
|
|
<h3><a class="anchor" id="autotoc_md26"></a>
|
|||
|
|
2.3.1、接口说明</h3>
|
|||
|
|
<ul>
|
|||
|
|
<li><p class="startli"><code>agile_modbus_slave_handle</code> 介绍</p>
|
|||
|
|
<div class="fragment"><div class="line"><span class="keywordtype">int</span> <a class="code hl_function" href="group___slave___operation___functions.html#ga9ddc38e7ac14384c02b07b8927165247">agile_modbus_slave_handle</a>(<a class="code hl_struct" href="structagile__modbus.html">agile_modbus_t</a> *ctx, <span class="keywordtype">int</span> msg_length, uint8_t slave_strict,</div>
|
|||
|
|
<div class="line"> <a class="code hl_typedef" href="group___slave___exported___types.html#gae66e6077fe07d589d91121ac8874541a">agile_modbus_slave_callback_t</a> slave_cb, <span class="keyword">const</span> <span class="keywordtype">void</span> *slave_data, <span class="keywordtype">int</span> *frame_length)</div>
|
|||
|
|
<div class="ttc" id="agroup___slave___exported___types_html_gae66e6077fe07d589d91121ac8874541a"><div class="ttname"><a href="group___slave___exported___types.html#gae66e6077fe07d589d91121ac8874541a">agile_modbus_slave_callback_t</a></div><div class="ttdeci">int(* agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data)</div><div class="ttdoc">从机回调函数</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus_8h_source.html#l00251">agile_modbus.h:251</a></div></div>
|
|||
|
|
<div class="ttc" id="agroup___slave___operation___functions_html_ga9ddc38e7ac14384c02b07b8927165247"><div class="ttname"><a href="group___slave___operation___functions.html#ga9ddc38e7ac14384c02b07b8927165247">agile_modbus_slave_handle</a></div><div class="ttdeci">int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict, agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length)</div><div class="ttdoc">从机数据处理</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus_8c_source.html#l01203">agile_modbus.c:1203</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus_html"><div class="ttname"><a href="structagile__modbus.html">agile_modbus</a></div><div class="ttdoc">Agile Modbus 结构体</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus_8h_source.html#l00203">agile_modbus.h:203</a></div></div>
|
|||
|
|
</div><!-- fragment --><p class="startli">msg_length: <code>等待数据接收结束</code> 后接收到的数据长度。</p>
|
|||
|
|
<p class="startli">slave_strict: 从机地址严格性检查 (0: 不判断地址是否一致,由用户回调处理; 1: 地址必须一致,否则不会调用回调,也不打包响应数据)。</p>
|
|||
|
|
<p class="startli">slave_cb: <code>agile_modbus_slave_callback_t</code> 类型回调函数,用户实现并传入。如果为 NULL,所有功能码都能响应且为成功,但寄存器数据依然为 0。</p>
|
|||
|
|
<p class="startli">slave_data: 从机回调函数私有数据。</p>
|
|||
|
|
<p class="startli">frame_length: 获取解析出的 modbus 数据帧长度。这个参数的意义在于:</p><ol type="1">
|
|||
|
|
<li>尾部有脏数据: 仍能解析成功,并告诉用户真实的 modbus 帧长,用户可以进行处理</li>
|
|||
|
|
<li>数据粘包: 数据由 <code>一帧完整的 modbus 数据 + 部分 modbus 数据帧</code> 组成,用户获得真实 modbus 帧长后,可以移除处理完的 modbus 数据帧,再次读取硬件接口数据与当前 <code>部分 modbus 数据帧</code> 组成新的一帧</li>
|
|||
|
|
<li>该参数在 modbus 广播传输大数据时使用较多(如:自定义功能码广播升级固件),普通的从机响应都是一问一答式,只处理完整数据帧就行,建议在响应前执行 <code>清空接收缓存</code></li>
|
|||
|
|
</ol>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code>agile_modbus_slave_callback_t</code> 介绍</p>
|
|||
|
|
<div class="fragment"><div class="line"> </div>
|
|||
|
|
<div class="line"><span class="keyword">typedef</span> int (*<a class="code hl_typedef" href="group___slave___exported___types.html#gae66e6077fe07d589d91121ac8874541a">agile_modbus_slave_callback_t</a>)(<a class="code hl_struct" href="structagile__modbus.html">agile_modbus_t</a> *ctx, <span class="keyword">struct </span><a class="code hl_struct" href="structagile__modbus__slave__info.html">agile_modbus_slave_info</a> *slave_info, <span class="keyword">const</span> <span class="keywordtype">void</span> *data);</div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__info_html"><div class="ttname"><a href="structagile__modbus__slave__info.html">agile_modbus_slave_info</a></div><div class="ttdoc">Agile Modbus 从机信息结构体</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus_8h_source.html#l00232">agile_modbus.h:232</a></div></div>
|
|||
|
|
</div><!-- fragment --><p class="startli"><code><a class="el" href="structagile__modbus__slave__info.html" title="Agile Modbus 从机信息结构体">agile_modbus_slave_info</a></code>:</p>
|
|||
|
|
<p class="startli">sft: 包含从机地址和功能码属性,回调中可利用</p>
|
|||
|
|
<p class="startli">rsp_length: 响应数据长度指针,回调中处理 <code>特殊功能码</code> 时需要更新其值,否则 <b>不准更改</b></p>
|
|||
|
|
<p class="startli">address: 寄存器地址 (不是所有功能码都用到)</p>
|
|||
|
|
<p class="startli">nb: 数目 (不是所有功能码都用到)</p>
|
|||
|
|
<p class="startli">buf: 不同功能码需要使用的数据域 (不是所有功能码都用到)</p>
|
|||
|
|
<p class="startli">send_index: 发送缓冲区当前索引 (不是所有功能码都用到)</p>
|
|||
|
|
</li>
|
|||
|
|
<li><code><a class="el" href="structagile__modbus__slave__info.html" title="Agile Modbus 从机信息结构体">agile_modbus_slave_info</a></code> 不同功能码使用<ul>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_READ_COILS、AGILE_MODBUS_FC_READ_DISCRETE_INPUTS</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>nb</code>、<code>send_index</code> 属性,需要调用 <code>agile_modbus_slave_io_set</code> API 将 IO 数据存放到 <code>ctx->send_buf + send_index</code> 开始的数据区域。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_READ_HOLDING_REGISTERS、AGILE_MODBUS_FC_READ_INPUT_REGISTERS</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>nb</code>、<code>send_index</code> 属性,需要调用 <code>agile_modbus_slave_register_set</code> API 将寄存器数据存放到 <code>ctx->send_buf + send_index</code> 开始的数据区域。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_WRITE_SINGLE_COIL、AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>buf</code> 属性,将 <code>buf</code> 强转为 <code>int *</code> 类型,获取值存放到寄存器中。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>nb</code>、<code>buf</code> 属性,需要调用 <code>agile_modbus_slave_io_get</code> API 获取要写入的 IO 数据。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>nb</code>、<code>buf</code> 属性,需要调用 <code>agile_modbus_slave_register_get</code> API 获取要写入的寄存器数据。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_MASK_WRITE_REGISTER</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>buf</code> 属性,通过 <code>(buf[0] << 8) + buf[1]</code> 获取 <code>and</code> 值,通过 <code>(buf[2] << 8) + buf[3]</code> 获取 <code>or</code> 值。获取寄存器值 <code>data</code>,进行 <code>data = (data & and) | (or & (~and))</code> 操作更新 <code>data</code> 值,写入寄存器。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS</p>
|
|||
|
|
<p class="startli">需要使用到 <code>address</code>、<code>buf</code>、<code>send_index</code> 属性,通过 <code>(buf[0] << 8) + buf[1]</code> 获取要读取的寄存器数目,通过 <code>(buf[2] << 8) + buf[3]</code> 获取要写入的寄存器地址,通过 <code>(buf[4] << 8) + buf[5]</code> 获取要写入的寄存器数目。需要调用 <code>agile_modbus_slave_register_get</code> API 获取要写入的寄存器数据,调用 <code>agile_modbus_slave_register_set</code> API 将寄存器数据存放到 <code>ctx->send_buf + send_index</code> 开始的数据区域。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">自定义功能码</p>
|
|||
|
|
<p class="startli">需要使用到 <code>send_index</code>、<code>nb</code>、<code>buf</code> 属性,用户在回调中处理数据。</p>
|
|||
|
|
<p class="startli">send_index: 发送缓冲区当前索引</p>
|
|||
|
|
<p class="startli">nb: PUD - 1,也就是 modbus 数据域长度</p>
|
|||
|
|
<p class="startli">buf: modbus 数据域起始位置</p>
|
|||
|
|
<p class="startli"><b>注意</b>: 用户在回调中往发送缓冲区填入数据后,需要更新 <code><a class="el" href="structagile__modbus__slave__info.html" title="Agile Modbus 从机信息结构体">agile_modbus_slave_info</a></code> 的 <code>rsp_length</code> 值。</p>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
<h3><a class="anchor" id="autotoc_md27"></a>
|
|||
|
|
2.3.2、简易从机接入接口</h3>
|
|||
|
|
<p >Agile Modbus 提供了 <code>agile_modbus_slave_callback_t</code> 的一种实现方式,使用户能够简单方便接入。</p>
|
|||
|
|
<p >使用示例可查看 <a href="./examples/slave">examples/slave</a>。</p>
|
|||
|
|
<p >使用方式:</p>
|
|||
|
|
<div class="fragment"><div class="line"><span class="preprocessor">#include "<a class="code" href="agile__modbus_8h.html">agile_modbus.h</a>"</span></div>
|
|||
|
|
<div class="line"><span class="preprocessor">#include "<a class="code" href="agile__modbus__slave__util_8h.html">agile_modbus_slave_util.h</a>"</span></div>
|
|||
|
|
<div class="line"> </div>
|
|||
|
|
<div class="line"><span class="keyword">const</span> <a class="code hl_struct" href="structagile__modbus__slave__util.html">agile_modbus_slave_util_t</a> slave_util = {</div>
|
|||
|
|
<div class="line"> <span class="comment">/* User implementation */</span></div>
|
|||
|
|
<div class="line"> </div>
|
|||
|
|
<div class="line">};</div>
|
|||
|
|
<div class="line"> </div>
|
|||
|
|
<div class="line"><a class="code hl_function" href="group___slave___operation___functions.html#ga9ddc38e7ac14384c02b07b8927165247">agile_modbus_slave_handle</a>(ctx, read_len, 0, <a class="code hl_function" href="group___s_l_a_v_e___u_t_i_l___exported___functions.html#ga6d7613fbda26c40a969df673cf9b8c5b">agile_modbus_slave_util_callback</a>, &slave_util, NULL);</div>
|
|||
|
|
<div class="ttc" id="aagile__modbus_8h_html"><div class="ttname"><a href="agile__modbus_8h.html">agile_modbus.h</a></div><div class="ttdoc">Agile Modbus 软件包通用头文件</div></div>
|
|||
|
|
<div class="ttc" id="aagile__modbus__slave__util_8h_html"><div class="ttname"><a href="agile__modbus__slave__util_8h.html">agile_modbus_slave_util.h</a></div><div class="ttdoc">Agile Modbus 软件包提供的简易从机接入头文件</div></div>
|
|||
|
|
<div class="ttc" id="agroup___s_l_a_v_e___u_t_i_l___exported___functions_html_ga6d7613fbda26c40a969df673cf9b8c5b"><div class="ttname"><a href="group___s_l_a_v_e___u_t_i_l___exported___functions.html#ga6d7613fbda26c40a969df673cf9b8c5b">agile_modbus_slave_util_callback</a></div><div class="ttdeci">int agile_modbus_slave_util_callback(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data)</div><div class="ttdoc">从机回调函数</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8c_source.html#l00387">agile_modbus_slave_util.c:387</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html"><div class="ttname"><a href="structagile__modbus__slave__util.html">agile_modbus_slave_util</a></div><div class="ttdoc">从机功能结构体</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00048">agile_modbus_slave_util.h:48</a></div></div>
|
|||
|
|
</div><!-- fragment --><ul>
|
|||
|
|
<li><code>agile_modbus_slave_util_callback</code> 介绍<ul>
|
|||
|
|
<li>Agile Modbus 提供的一种 <code>agile_modbus_slave_callback_t</code> 实现方式,需要 <code>agile_modbus_slave_util_t</code> 类型变量指针作为私有数据。</li>
|
|||
|
|
<li>私有数据为 NULL,所有功能码都能响应且为成功,但寄存器数据依然为 0。</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code>agile_modbus_slave_util_t</code> 介绍</p>
|
|||
|
|
<div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code hl_struct" href="structagile__modbus__slave__util.html">agile_modbus_slave_util</a> {</div>
|
|||
|
|
<div class="line"> <span class="keyword">const</span> <a class="code hl_struct" href="structagile__modbus__slave__util__map.html">agile_modbus_slave_util_map_t</a> *<a class="code hl_variable" href="structagile__modbus__slave__util.html#adf60d2aacae135df7fb77f1fd567a0f3">tab_bits</a>; </div>
|
|||
|
|
<div class="line"> <span class="keywordtype">int</span> <a class="code hl_variable" href="structagile__modbus__slave__util.html#a54d8cd5ea2ece03fc4748f857d433470">nb_bits</a>; </div>
|
|||
|
|
<div class="line"> <span class="keyword">const</span> <a class="code hl_struct" href="structagile__modbus__slave__util__map.html">agile_modbus_slave_util_map_t</a> *<a class="code hl_variable" href="structagile__modbus__slave__util.html#ab8dd5a6fa6cb534aa90460cf9a71ae6f">tab_input_bits</a>; </div>
|
|||
|
|
<div class="line"> <span class="keywordtype">int</span> <a class="code hl_variable" href="structagile__modbus__slave__util.html#a81fb44a47ea6e8dc7eb190b87ddb6dc4">nb_input_bits</a>; </div>
|
|||
|
|
<div class="line"> <span class="keyword">const</span> <a class="code hl_struct" href="structagile__modbus__slave__util__map.html">agile_modbus_slave_util_map_t</a> *<a class="code hl_variable" href="structagile__modbus__slave__util.html#ae21eece6d89b5d46839496e9281108f8">tab_registers</a>; </div>
|
|||
|
|
<div class="line"> <span class="keywordtype">int</span> <a class="code hl_variable" href="structagile__modbus__slave__util.html#ac7c7bd2cc1687ae7c291a054d3071114">nb_registers</a>; </div>
|
|||
|
|
<div class="line"> <span class="keyword">const</span> <a class="code hl_struct" href="structagile__modbus__slave__util__map.html">agile_modbus_slave_util_map_t</a> *<a class="code hl_variable" href="structagile__modbus__slave__util.html#a67c8df610dcb3f8dee4d32ed920f4886">tab_input_registers</a>; </div>
|
|||
|
|
<div class="line"> <span class="keywordtype">int</span> <a class="code hl_variable" href="structagile__modbus__slave__util.html#a3c2c64bb74a0cab7f34f303fa3a37b31">nb_input_registers</a>; </div>
|
|||
|
|
<div class="line"> int (*<a class="code hl_variable" href="structagile__modbus__slave__util.html#a134270ba34165c677e85490b2bb6719c">addr_check</a>)(<a class="code hl_struct" href="structagile__modbus.html">agile_modbus_t</a> *ctx, <span class="keyword">struct </span><a class="code hl_struct" href="structagile__modbus__slave__info.html">agile_modbus_slave_info</a> *slave_info); </div>
|
|||
|
|
<div class="line"> int (*<a class="code hl_variable" href="structagile__modbus__slave__util.html#a70de0b2f19492b188c99ba332e2b2ffa">special_function</a>)(<a class="code hl_struct" href="structagile__modbus.html">agile_modbus_t</a> *ctx, <span class="keyword">struct </span><a class="code hl_struct" href="structagile__modbus__slave__info.html">agile_modbus_slave_info</a> *slave_info); </div>
|
|||
|
|
<div class="line"> int (*<a class="code hl_variable" href="structagile__modbus__slave__util.html#abc6323db9d3873c30bee0e7efe96f4b8">done</a>)(<a class="code hl_struct" href="structagile__modbus.html">agile_modbus_t</a> *ctx, <span class="keyword">struct </span><a class="code hl_struct" href="structagile__modbus__slave__info.html">agile_modbus_slave_info</a> *slave_info, <span class="keywordtype">int</span> ret); </div>
|
|||
|
|
<div class="line">} <a class="code hl_typedef" href="group___s_l_a_v_e___u_t_i_l___exported___types.html#ga48cf733bea0cf7ad09b52b139348de50">agile_modbus_slave_util_t</a>;</div>
|
|||
|
|
<div class="ttc" id="agroup___s_l_a_v_e___u_t_i_l___exported___types_html_ga48cf733bea0cf7ad09b52b139348de50"><div class="ttname"><a href="group___s_l_a_v_e___u_t_i_l___exported___types.html#ga48cf733bea0cf7ad09b52b139348de50">agile_modbus_slave_util_t</a></div><div class="ttdeci">struct agile_modbus_slave_util agile_modbus_slave_util_t</div><div class="ttdoc">从机功能结构体</div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util__map_html"><div class="ttname"><a href="structagile__modbus__slave__util__map.html">agile_modbus_slave_util_map</a></div><div class="ttdoc">从机寄存器映射结构体</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00038">agile_modbus_slave_util.h:38</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_a134270ba34165c677e85490b2bb6719c"><div class="ttname"><a href="structagile__modbus__slave__util.html#a134270ba34165c677e85490b2bb6719c">agile_modbus_slave_util::addr_check</a></div><div class="ttdeci">int(* addr_check)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info)</div><div class="ttdoc">地址检查接口</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00057">agile_modbus_slave_util.h:57</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_a3c2c64bb74a0cab7f34f303fa3a37b31"><div class="ttname"><a href="structagile__modbus__slave__util.html#a3c2c64bb74a0cab7f34f303fa3a37b31">agile_modbus_slave_util::nb_input_registers</a></div><div class="ttdeci">int nb_input_registers</div><div class="ttdoc">输入寄存器定义数组数目</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00056">agile_modbus_slave_util.h:56</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_a54d8cd5ea2ece03fc4748f857d433470"><div class="ttname"><a href="structagile__modbus__slave__util.html#a54d8cd5ea2ece03fc4748f857d433470">agile_modbus_slave_util::nb_bits</a></div><div class="ttdeci">int nb_bits</div><div class="ttdoc">线圈寄存器定义数组数目</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00050">agile_modbus_slave_util.h:50</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_a67c8df610dcb3f8dee4d32ed920f4886"><div class="ttname"><a href="structagile__modbus__slave__util.html#a67c8df610dcb3f8dee4d32ed920f4886">agile_modbus_slave_util::tab_input_registers</a></div><div class="ttdeci">const agile_modbus_slave_util_map_t * tab_input_registers</div><div class="ttdoc">输入寄存器定义数组</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00055">agile_modbus_slave_util.h:55</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_a70de0b2f19492b188c99ba332e2b2ffa"><div class="ttname"><a href="structagile__modbus__slave__util.html#a70de0b2f19492b188c99ba332e2b2ffa">agile_modbus_slave_util::special_function</a></div><div class="ttdeci">int(* special_function)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info)</div><div class="ttdoc">特殊功能码处理接口</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00058">agile_modbus_slave_util.h:58</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_a81fb44a47ea6e8dc7eb190b87ddb6dc4"><div class="ttname"><a href="structagile__modbus__slave__util.html#a81fb44a47ea6e8dc7eb190b87ddb6dc4">agile_modbus_slave_util::nb_input_bits</a></div><div class="ttdeci">int nb_input_bits</div><div class="ttdoc">离散量输入寄存器定义数组数目</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00052">agile_modbus_slave_util.h:52</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_ab8dd5a6fa6cb534aa90460cf9a71ae6f"><div class="ttname"><a href="structagile__modbus__slave__util.html#ab8dd5a6fa6cb534aa90460cf9a71ae6f">agile_modbus_slave_util::tab_input_bits</a></div><div class="ttdeci">const agile_modbus_slave_util_map_t * tab_input_bits</div><div class="ttdoc">离散量输入寄存器定义数组</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00051">agile_modbus_slave_util.h:51</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_abc6323db9d3873c30bee0e7efe96f4b8"><div class="ttname"><a href="structagile__modbus__slave__util.html#abc6323db9d3873c30bee0e7efe96f4b8">agile_modbus_slave_util::done</a></div><div class="ttdeci">int(* done)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, int ret)</div><div class="ttdoc">处理结束接口</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00059">agile_modbus_slave_util.h:59</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_ac7c7bd2cc1687ae7c291a054d3071114"><div class="ttname"><a href="structagile__modbus__slave__util.html#ac7c7bd2cc1687ae7c291a054d3071114">agile_modbus_slave_util::nb_registers</a></div><div class="ttdeci">int nb_registers</div><div class="ttdoc">保持寄存器定义数组数目</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00054">agile_modbus_slave_util.h:54</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_adf60d2aacae135df7fb77f1fd567a0f3"><div class="ttname"><a href="structagile__modbus__slave__util.html#adf60d2aacae135df7fb77f1fd567a0f3">agile_modbus_slave_util::tab_bits</a></div><div class="ttdeci">const agile_modbus_slave_util_map_t * tab_bits</div><div class="ttdoc">线圈寄存器定义数组</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00049">agile_modbus_slave_util.h:49</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util_html_ae21eece6d89b5d46839496e9281108f8"><div class="ttname"><a href="structagile__modbus__slave__util.html#ae21eece6d89b5d46839496e9281108f8">agile_modbus_slave_util::tab_registers</a></div><div class="ttdeci">const agile_modbus_slave_util_map_t * tab_registers</div><div class="ttdoc">保持寄存器定义数组</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00053">agile_modbus_slave_util.h:53</a></div></div>
|
|||
|
|
</div><!-- fragment --><ul>
|
|||
|
|
<li><p class="startli">寄存器相关</p>
|
|||
|
|
<p class="startli">用户需要实现 <code>bits</code>、<code>input_bits</code>、<code>registers</code>、<code>input_registers</code> 定义。如果某个寄存器定义为 NULL,该寄存器对应的功能码能响应且为成功,但寄存器数据都为 0。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli">接口调用过程</p>
|
|||
|
|
<p class="startli"><img src="./figures/SlaveCallback.jpg" alt="SlaveCallback" class="inline"/></p>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code><a class="el" href="structagile__modbus__slave__util__map.html" title="从机寄存器映射结构体">agile_modbus_slave_util_map</a></code> 介绍</p>
|
|||
|
|
<div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code hl_struct" href="structagile__modbus__slave__util__map.html">agile_modbus_slave_util_map</a> {</div>
|
|||
|
|
<div class="line"> <span class="keywordtype">int</span> <a class="code hl_variable" href="structagile__modbus__slave__util__map.html#a9b130b4a875dca0d63c31d81fbc8b0f1">start_addr</a>; </div>
|
|||
|
|
<div class="line"> <span class="keywordtype">int</span> <a class="code hl_variable" href="structagile__modbus__slave__util__map.html#ace624a13ffd6380963e9173d6f8f4eb9">end_addr</a>; </div>
|
|||
|
|
<div class="line"> int (*<a class="code hl_variable" href="structagile__modbus__slave__util__map.html#a7fd43329330824f98bdd5da3e8b8f170">get</a>)(<span class="keywordtype">void</span> *buf, <span class="keywordtype">int</span> bufsz); </div>
|
|||
|
|
<div class="line"> int (*<a class="code hl_variable" href="structagile__modbus__slave__util__map.html#aeb703aff86edfb371edb56e0122d51ab">set</a>)(<span class="keywordtype">int</span> index, <span class="keywordtype">int</span> len, <span class="keywordtype">void</span> *buf, <span class="keywordtype">int</span> bufsz); </div>
|
|||
|
|
<div class="line">} <a class="code hl_typedef" href="group___s_l_a_v_e___u_t_i_l___exported___types.html#ga704dafcb7fb13e228bfbf8744dd5a3f8">agile_modbus_slave_util_map_t</a>;</div>
|
|||
|
|
<div class="ttc" id="agroup___s_l_a_v_e___u_t_i_l___exported___types_html_ga704dafcb7fb13e228bfbf8744dd5a3f8"><div class="ttname"><a href="group___s_l_a_v_e___u_t_i_l___exported___types.html#ga704dafcb7fb13e228bfbf8744dd5a3f8">agile_modbus_slave_util_map_t</a></div><div class="ttdeci">struct agile_modbus_slave_util_map agile_modbus_slave_util_map_t</div><div class="ttdoc">从机寄存器映射结构体</div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util__map_html_a7fd43329330824f98bdd5da3e8b8f170"><div class="ttname"><a href="structagile__modbus__slave__util__map.html#a7fd43329330824f98bdd5da3e8b8f170">agile_modbus_slave_util_map::get</a></div><div class="ttdeci">int(* get)(void *buf, int bufsz)</div><div class="ttdoc">获取寄存器数据接口</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00041">agile_modbus_slave_util.h:41</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util__map_html_a9b130b4a875dca0d63c31d81fbc8b0f1"><div class="ttname"><a href="structagile__modbus__slave__util__map.html#a9b130b4a875dca0d63c31d81fbc8b0f1">agile_modbus_slave_util_map::start_addr</a></div><div class="ttdeci">int start_addr</div><div class="ttdoc">起始地址</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00039">agile_modbus_slave_util.h:39</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util__map_html_ace624a13ffd6380963e9173d6f8f4eb9"><div class="ttname"><a href="structagile__modbus__slave__util__map.html#ace624a13ffd6380963e9173d6f8f4eb9">agile_modbus_slave_util_map::end_addr</a></div><div class="ttdeci">int end_addr</div><div class="ttdoc">结束地址</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00040">agile_modbus_slave_util.h:40</a></div></div>
|
|||
|
|
<div class="ttc" id="astructagile__modbus__slave__util__map_html_aeb703aff86edfb371edb56e0122d51ab"><div class="ttname"><a href="structagile__modbus__slave__util__map.html#aeb703aff86edfb371edb56e0122d51ab">agile_modbus_slave_util_map::set</a></div><div class="ttdeci">int(* set)(int index, int len, void *buf, int bufsz)</div><div class="ttdoc">设置寄存器数据接口</div><div class="ttdef"><b>Definition:</b> <a href="agile__modbus__slave__util_8h_source.html#l00042">agile_modbus_slave_util.h:42</a></div></div>
|
|||
|
|
</div><!-- fragment --><ul>
|
|||
|
|
<li><b>注意事项</b>:<ul>
|
|||
|
|
<li>起始地址和结束地址决定的寄存器个数有限制。更改函数内部 <code>map_buf</code> 数组大小可使其变大。<ul>
|
|||
|
|
<li>bit 寄存器 < 250</li>
|
|||
|
|
<li>register 寄存器 < 125</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
<li>接口函数为 NULL,寄存器对应的功能码能响应且为成功。</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code>get</code> 接口</p>
|
|||
|
|
<p class="startli">将地址域内的数据全部拷贝到 <code>buf</code> 中。</p>
|
|||
|
|
</li>
|
|||
|
|
<li><p class="startli"><code>set</code> 接口</p><ul>
|
|||
|
|
<li><code>index</code>: 地址域内的偏移</li>
|
|||
|
|
<li><code>len</code>: 长度</li>
|
|||
|
|
</ul>
|
|||
|
|
<p class="startli">根据 <code>index</code> 和 <code>len</code> 修改数据。</p>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md28"></a>
|
|||
|
|
2.4、示例</h2>
|
|||
|
|
<ul>
|
|||
|
|
<li><a href="./examples">examples</a> 文件夹中提供 PC 上的示例,可以在 <code>WSL</code> 或 <code>Linux</code> 下编译运行。<ul>
|
|||
|
|
<li>RTU / TCP 主机、从机的示例</li>
|
|||
|
|
<li><p class="startli">特殊功能码的示例</p>
|
|||
|
|
<p class="startli">RTU 点对点传输文件: 演示特殊功能码的使用方式</p>
|
|||
|
|
<p class="startli">RTU 广播传输文件: 演示 <code>agile_modbus_slave_handle</code> 中 <code>frame_length</code> 的用处</p>
|
|||
|
|
</li>
|
|||
|
|
</ul>
|
|||
|
|
</li>
|
|||
|
|
<li><a href="https://github.com/loogg/agile_modbus_mcu_demos">mcu_demos</a> 提供在 MCU 上的例子。</li>
|
|||
|
|
<li><a href="https://github.com/loogg/AT32F437_Boot">AT32F437_Boot</a> 在 AT32F437 上基于 RT-Thread 实现的支持 Modbus 固件升级的 Bootloader。</li>
|
|||
|
|
<li><a href="https://github.com/loogg/HPM6750_Boot">HPM6750_Boot</a> 在 HPM6750 上基于 RT-Thread 实现的支持 Modbus 固件升级的 Bootloader。</li>
|
|||
|
|
</ul>
|
|||
|
|
<h2><a class="anchor" id="autotoc_md29"></a>
|
|||
|
|
2.5、Doxygen 文档生成</h2>
|
|||
|
|
<ul>
|
|||
|
|
<li>使用 <code>Doxywizard</code> 打开 <a href="./doc/doxygen/Doxyfile">Doxyfile</a> 运行,生成的文件在 <a href="./doc/doxygen/output">doxygen/output</a> 下。</li>
|
|||
|
|
<li>需要更改 <code>Graphviz</code> 路径。</li>
|
|||
|
|
<li><code>HTML</code> 生成未使用 <code>chm</code> 格式的,如果使能需要更改 <code>hhc.exe</code> 路径。</li>
|
|||
|
|
</ul>
|
|||
|
|
<h1><a class="anchor" id="autotoc_md30"></a>
|
|||
|
|
3、支持</h1>
|
|||
|
|
<p ><img src="./figures/zanshang.jpg" alt="zanshang" class="inline"/></p>
|
|||
|
|
<p >如果 Agile Modbus 解决了你的问题,不妨扫描上面二维码请我 <b>喝杯咖啡</b> ~</p>
|
|||
|
|
<h1><a class="anchor" id="autotoc_md31"></a>
|
|||
|
|
4、联系方式 & 感谢</h1>
|
|||
|
|
<ul>
|
|||
|
|
<li>维护:马龙伟</li>
|
|||
|
|
<li>主页:<a href="https://github.com/loogg/agile_modbus">https://github.com/loogg/agile_modbus</a></li>
|
|||
|
|
<li>邮箱:<a href="#" onclick="location.href='mai'+'lto:'+'254'+'40'+'472'+'13'+'@qq'+'.c'+'om'; return false;">25440<span style="display: none;">.nosp@m.</span>4721<span style="display: none;">.nosp@m.</span>3@qq.<span style="display: none;">.nosp@m.</span>com</a> </li>
|
|||
|
|
</ul>
|
|||
|
|
</div></div><!-- PageDoc -->
|
|||
|
|
</div><!-- contents -->
|
|||
|
|
</div><!-- doc-content -->
|
|||
|
|
<!-- start footer part -->
|
|||
|
|
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
|||
|
|
<ul>
|
|||
|
|
<li class="footer">制作者 <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.2 </li>
|
|||
|
|
</ul>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>
|