Files
UKSI_TEST/AllLibs/Modbus/Doc/html/index.html
2025-12-16 17:57:59 +03:00

363 lines
44 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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" lang="en-US">
<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.14.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Modbus: Инструкция по подключению релиза библиотеки STM 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>
<script type="text/javascript" src="clipboard.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript" src="cookie.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>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["tex2jax.js"],
jax: ["input/TeX","output/HTML-CSS"],
});
</script>
<script type="text/javascript" async="async" src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js"></script>
<script type="text/javascript" src="darkmode_toggle.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 id="projectrow">
<td id="projectalign">
<div id="projectname">Modbus<span id="projectnumber">&#160;0.3</span>
</div>
<div id="projectbrief">Библиотека Modbus для STM</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.14.0 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search/",'.html');
</script>
<script type="text/javascript">
$(function() { codefold.init(); });
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',true,false,'search.php','Search',true);
$(function() { init_search(); });
});
</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">
$(function(){initNavTree('index.html','',''); });
</script>
<div id="container">
<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">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div><div class="header">
<div class="headertitle"><div class="title">Инструкция по подключению релиза библиотеки <span class="tt">STM Modbus</span> </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="md__e_1_2_8_w_o_r_k_2_s_t_m32_2_diod___test_2diode__tester_2_core_2_modbus_2_r_e_a_d_m_e"></a></p>
<p>Данная библиотека подключается напрямую из Git, как субмодуль. Позволяя при желании обновлять её напрямую через git.</p>
<h1 class="doxsection"><a class="anchor" id="структура-библиотеки"></a>
Структура библиотеки</h1>
<p>*Note: Файлы начинающиеся с <span class="tt">__</span> и которых <b>нет</b> в этом дереве являются **внутренними/непротестированными/недокументированными*** </p><div class="fragment"><div class="line">Modbus/ Иерархия модулей:</div>
<div class="line">│ inc/ modbus</div>
<div class="line">│ ├── modbus.h # Главный заголовочный файл modbus_slave</div>
<div class="line">│ ├── modbus_core.h # Базовые определения и структуры modbus_master</div>
<div class="line">│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils</div>
<div class="line">│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs</div>
<div class="line">│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs</div>
<div class="line">│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid</div>
<div class="line">│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag</div>
<div class="line">├── src/ └── rs_message</div>
<div class="line">│ ├── modbus.c # Основная логика Modbus │</div>
<div class="line">│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро)</div>
<div class="line">│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config</div>
<div class="line">│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data</div>
<div class="line">│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs</div>
<div class="line">│ ├── modbus_inputregs.c # Реализация входных регистров </div>
<div class="line">│ ├── modbus_devid.c # Реализация идентификации устройства </div>
<div class="line">│ ├── modbus_data.c # Функции доступа к данным </div>
<div class="line">│ └── rs_message.c # Реализация драйвера RS </div>
<div class="line">├── __modbus_config.h # Конфигурация Modbus (надо заменить) </div>
<div class="line">├── __modbus_data.h # Структуры данных (надо заменить) </div>
<div class="line">└── __modbus_data.c # Функции доступа (надо заменить) </div>
</div><!-- fragment --><h1 class="doxsection"><a class="anchor" id="инструкция-по-подключению"></a>
Инструкция по подключению</h1>
<h2 class="doxsection"><a class="anchor" id="autotoc_md1-склонируйте-субмодуль-в-ваш-проект"></a>
1. <b>Склонируйте субмодуль</b> в ваш проект:</h2>
<div class="fragment"><div class="line">git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus</div>
<div class="line">git submodule update --init --recursive</div>
</div><!-- fragment --><h2 class="doxsection"><a class="anchor" id="autotoc_md2-скопируйте-файлы-конфигурации-в-отдельную-папку-в-вашем-проекте-вне-субмодуля-и-удалите-__-из-имени-файлов"></a>
2. <b>Скопируйте файлы конфигурации</b> в отдельную папку в вашем проекте (вне субмодуля) и удалите <span class="tt">__</span> из имени файлов:</h2>
<div class="fragment"><div class="line">ProjectRoot/</div>
<div class="line">├── Configs/</div>
<div class="line">│ ├── modbus_config.h # скопировать из __modbus_config.h</div>
<div class="line">│ ├── modbus_data.h # скопировать из __modbus_data.h</div>
<div class="line">│ └── modbus_data.c # скопировать из __modbus_data.c</div>
<div class="line">└── Modbus/ # Субмодуль</div>
</div><!-- fragment --><h2 class="doxsection"><a class="anchor" id="autotoc_md3-настройте-конфигурацию-под-ваш-проект"></a>
3. <b>Настройте конфигурацию</b> под ваш проект:</h2>
<h3 class="doxsection"><a class="anchor" id="autotoc_md31-настройка-периферии"></a>
3.1. Настройка периферии</h3>
<ul>
<li><b>UART</b>: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1</li>
<li><b>TIM</b>: Настройте таймер для генерации прерываний (например, 1ms tick)</li>
<li><b>Включите прерывания</b> для UART и TIM</li>
</ul>
<h3 class="doxsection"><a class="anchor" id="autotoc_md32-подключение-обработчиков-прерываний"></a>
3.2. Подключение обработчиков прерываний</h3>
<p>Подключите обработчики прерываний <b>UART</b> и <b>TIM</b> в свои IRQ обработчики <em><b>вместо</b></em> HAL-обработчиков:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="modbus_8h.html">modbus.h</a>&quot;</span></div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> USARTx_IRQHandler(<span class="keywordtype">void</span>)</div>
<div class="line">{</div>
<div class="line"> <a class="code hl_function" href="group___r_s___t_o_o_l_s.html#gab27567456df0329130c7fe4fc43c6ee1">RS_UART_Handler</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>);</div>
<div class="line"> <span class="keywordflow">return</span>;</div>
<div class="line"> HAL_UART_IRQHandler(&amp;huart);</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span> TIMx_IRQHandler(<span class="keywordtype">void</span>)</div>
<div class="line">{</div>
<div class="line"> <a class="code hl_function" href="group___r_s___t_o_o_l_s.html#ga2d356b2a0b4af43460bb2cacb81779ce">RS_TIM_Handler</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>);</div>
<div class="line"> <span class="keywordflow">return</span>;</div>
<div class="line"> HAL_TIM_IRQHandler(&amp;htim);</div>
<div class="line">}</div>
<div class="ttc" id="agroup___r_s___t_o_o_l_s_html_ga2d356b2a0b4af43460bb2cacb81779ce"><div class="ttname"><a href="group___r_s___t_o_o_l_s.html#ga2d356b2a0b4af43460bb2cacb81779ce">RS_TIM_Handler</a></div><div class="ttdeci">void RS_TIM_Handler(RS_HandleTypeDef *hRS)</div><div class="ttdoc">Обработчик прерывания TIM.</div><div class="ttdef"><b>Definition</b> <a href="rs__message_8c_source.html#l00433">rs_message.c:433</a></div></div>
<div class="ttc" id="agroup___r_s___t_o_o_l_s_html_gab27567456df0329130c7fe4fc43c6ee1"><div class="ttname"><a href="group___r_s___t_o_o_l_s.html#gab27567456df0329130c7fe4fc43c6ee1">RS_UART_Handler</a></div><div class="ttdeci">void RS_UART_Handler(RS_HandleTypeDef *hRS)</div><div class="ttdoc">Обработчик прерывания UART.</div><div class="ttdef"><b>Definition</b> <a href="rs__message_8c_source.html#l00320">rs_message.c:320</a></div></div>
<div class="ttc" id="agroup___r_s___t_o_o_l_s_html_gadaef5cb7e494d0fd139199f5b6cbeb86"><div class="ttname"><a href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a></div><div class="ttdeci">RS_HandleTypeDef hmodbus1</div><div class="ttdoc">Default Handle for Modbus.</div><div class="ttdef"><b>Definition</b> <a href="modbus_8c_source.html#l00024">modbus.c:24</a></div></div>
<div class="ttc" id="amodbus_8h_html"><div class="ttname"><a href="modbus_8h.html">modbus.h</a></div><div class="ttdoc">Главный заголовочный файл Modbus библиотеки</div></div>
</div><!-- fragment --> <h3 class="doxsection"><a class="anchor" id="autotoc_md33-в-modbus_configh-укажите-параметры-устройства"></a>
3.3. В <span class="tt">modbus_config.h</span> укажите параметры устройства</h3>
<h3 class="doxsection"><a class="anchor" id="autotoc_md34-инициализация-в-коде"></a>
3.4. Инициализация в коде</h3>
<p>Чтобы настроить Slave-режим <span class="tt">main()</span> после инициализации HAL:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="modbus_8h.html">modbus.h</a>&quot;</span></div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">void</span>)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Инициализация HAL</span></div>
<div class="line"> HAL_Init();</div>
<div class="line"> SystemClock_Config();</div>
<div class="line"> MX_GPIO_Init();</div>
<div class="line"> MX_USART1_UART_Init();</div>
<div class="line"> MX_TIM3_Init();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Инициализация Modbus</span></div>
<div class="line"> <a class="code hl_function" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga9e787c3454aab3293dec6e6795f687f5">MODBUS_FirstInit</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>, &amp;<a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga370986118b8227cb6cb33c6b748fbbcb">mb_huart</a>, &amp;<a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga6723a1608946a4f86cd7c9c7e614d04e">mb_htim</a>);</div>
<div class="line"> <a class="code hl_function" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga460466907693a256487d31f09b16edfe">MODBUS_Config</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>, <a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#gab9b18e108b98b225a52c5ccca58e7f2b">MODBUS_DEVICE_ID</a>, <a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga66f7c59a25c8cca6d5b0991895c26b69">MODBUS_TIMEOUT</a>, <a class="code hl_define" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#gac0b3749af91f1007fd0291157b66b305">MODBUS_MODE_SLAVE</a>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Запуск приема Modbus</span></div>
<div class="line"> <a class="code hl_function" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga9a17402983188566254b7096342ba69e">MODBUS_SlaveStart</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>, NULL);</div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">while</span> (1)</div>
<div class="line"> {</div>
<div class="line"> <span class="comment">// Основной цикл</span></div>
<div class="line"> }</div>
<div class="line">}</div>
<div class="ttc" id="agroup___m_o_d_b_u_s___c_o_n_f_i_g_s_html_ga370986118b8227cb6cb33c6b748fbbcb"><div class="ttname"><a href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga370986118b8227cb6cb33c6b748fbbcb">mb_huart</a></div><div class="ttdeci">#define mb_huart</div><div class="ttdoc">Удобный дефайн для модбасовского uart.</div><div class="ttdef"><b>Definition</b> <a href="modbus__config_8h_source.html#l00041">modbus_config.h:41</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___c_o_n_f_i_g_s_html_ga66f7c59a25c8cca6d5b0991895c26b69"><div class="ttname"><a href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga66f7c59a25c8cca6d5b0991895c26b69">MODBUS_TIMEOUT</a></div><div class="ttdeci">#define MODBUS_TIMEOUT</div><div class="ttdoc">Таймаут в тиках таймера</div><div class="ttdef"><b>Definition</b> <a href="modbus__config_8h_source.html#l00026">modbus_config.h:26</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___c_o_n_f_i_g_s_html_ga6723a1608946a4f86cd7c9c7e614d04e"><div class="ttname"><a href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga6723a1608946a4f86cd7c9c7e614d04e">mb_htim</a></div><div class="ttdeci">#define mb_htim</div><div class="ttdoc">Удобный дефайн для модбасовского таймера</div><div class="ttdef"><b>Definition</b> <a href="modbus__config_8h_source.html#l00042">modbus_config.h:42</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___c_o_n_f_i_g_s_html_gab9b18e108b98b225a52c5ccca58e7f2b"><div class="ttname"><a href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#gab9b18e108b98b225a52c5ccca58e7f2b">MODBUS_DEVICE_ID</a></div><div class="ttdeci">#define MODBUS_DEVICE_ID</div><div class="ttdoc">Адрес устройства в сети Modbus.</div><div class="ttdef"><b>Definition</b> <a href="modbus__config_8h_source.html#l00025">modbus_config.h:25</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s_html_ga460466907693a256487d31f09b16edfe"><div class="ttname"><a href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga460466907693a256487d31f09b16edfe">MODBUS_Config</a></div><div class="ttdeci">HAL_StatusTypeDef MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master)</div><div class="ttdoc">Программная конфигурация модбас.</div><div class="ttdef"><b>Definition</b> <a href="modbus_8c_source.html#l00072">modbus.c:72</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s_html_ga9a17402983188566254b7096342ba69e"><div class="ttname"><a href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga9a17402983188566254b7096342ba69e">MODBUS_SlaveStart</a></div><div class="ttdeci">HAL_StatusTypeDef MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)</div><div class="ttdoc">Запуск слейв модбас.</div><div class="ttdef"><b>Definition</b> <a href="modbus_8c_source.html#l00105">modbus.c:105</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s_html_ga9e787c3454aab3293dec6e6795f687f5"><div class="ttname"><a href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga9e787c3454aab3293dec6e6795f687f5">MODBUS_FirstInit</a></div><div class="ttdeci">HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim)</div><div class="ttdoc">Инициализация периферии модбас.</div><div class="ttdef"><b>Definition</b> <a href="modbus_8c_source.html#l00042">modbus.c:42</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s_html_gac0b3749af91f1007fd0291157b66b305"><div class="ttname"><a href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#gac0b3749af91f1007fd0291157b66b305">MODBUS_MODE_SLAVE</a></div><div class="ttdeci">#define MODBUS_MODE_SLAVE</div><div class="ttdoc">Псевдо-enum: Режим слейв</div><div class="ttdef"><b>Definition</b> <a href="modbus_8h_source.html#l00117">modbus.h:117</a></div></div>
</div><!-- fragment --><p> Чтобы настроить Master-режим <span class="tt">main()</span> после инициализации HAL:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="modbus_8h.html">modbus.h</a>&quot;</span></div>
<div class="line"><span class="comment">// Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук</span></div>
<div class="line"><a class="code hl_struct" href="struct_r_s___msg_type_def.html">RS_MsgTypeDef</a> read_hold_cmd = <a class="code hl_function" href="group___m_o_d_b_u_s___r_e_q_u_e_s_t___m_s_g.html#ga4a4798a15608f3aac04150115a628f8e">MB_REQUEST_READ_HOLDING_REGS</a>(1, 0, 10);</div>
<div class="line"><span class="comment">// коллбек, вызовется при получении ответа от слейва</span></div>
<div class="line">read_hold[10];</div>
<div class="line"><span class="keywordtype">void</span> callback_func(<a class="code hl_struct" href="struct_r_s___handle_type_def.html">RS_HandleTypeDef</a> *hmodbus, <a class="code hl_struct" href="struct_r_s___msg_type_def.html">RS_MsgTypeDef</a> *modbus_msg) </div>
<div class="line">{</div>
<div class="line"> <span class="comment">// MB_RespGet_... Чтобы достать нужные данные из ответа</span></div>
<div class="line"> <span class="keywordflow">if</span>(hmodbus-&gt;<a class="code hl_variable" href="struct_r_s___handle_type_def.html#a8bbcb263ae7a61790b559bcb55cd9aa9">RS_STATUS</a> == RS_OK)</div>
<div class="line"> {</div>
<div class="line"> <span class="keywordflow">for</span>(<span class="keywordtype">int</span> addr = <a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>.Addr; addr &lt; <a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>.Addr + <a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>.Qnt; addr++)</div>
<div class="line"> {</div>
<div class="line"> uint16_t value;</div>
<div class="line"> <span class="keywordflow">if</span>(<a class="code hl_function" href="group___m_o_d_b_u_s___r_e_g_s___a_p_i.html#ga1f80317087624a23f84224c6f2c1d596">MB_RespGet_RegisterValue</a>(&amp;<a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>, addr, &amp;value))</div>
<div class="line"> {</div>
<div class="line"> read_hold[i] = value;</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line"> }</div>
<div class="line">}</div>
<div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">void</span>)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Инициализация HAL</span></div>
<div class="line"> HAL_Init();</div>
<div class="line"> SystemClock_Config();</div>
<div class="line"> MX_GPIO_Init();</div>
<div class="line"> MX_USART1_UART_Init();</div>
<div class="line"> MX_TIM3_Init();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Инициализация Modbus</span></div>
<div class="line"> <a class="code hl_function" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga9e787c3454aab3293dec6e6795f687f5">MODBUS_FirstInit</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>, &amp;<a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga370986118b8227cb6cb33c6b748fbbcb">mb_huart</a>, &amp;<a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga6723a1608946a4f86cd7c9c7e614d04e">mb_htim</a>);</div>
<div class="line"> <a class="code hl_function" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga460466907693a256487d31f09b16edfe">MODBUS_Config</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>, 0, <a class="code hl_define" href="group___m_o_d_b_u_s___c_o_n_f_i_g_s.html#ga66f7c59a25c8cca6d5b0991895c26b69">MODBUS_TIMEOUT</a>, <a class="code hl_define" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#gad91eec9c3350f2705f1bbe1856cb0159">MODBUS_MODE_MASTER</a>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Запрос по Modbus</span></div>
<div class="line"> <a class="code hl_function" href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga19090cabfba2345391e37398125a2f55">MODBUS_MasterRequest</a>(&amp;<a class="code hl_variable" href="group___r_s___t_o_o_l_s.html#gadaef5cb7e494d0fd139199f5b6cbeb86">hmodbus1</a>, &amp;read_hold_cmd, &amp;callback_func);</div>
<div class="line"> </div>
<div class="line">}</div>
<div class="ttc" id="agroup___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s_html_ga19090cabfba2345391e37398125a2f55"><div class="ttname"><a href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#ga19090cabfba2345391e37398125a2f55">MODBUS_MasterRequest</a></div><div class="ttdeci">HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, void(*pClbk)(RS_HandleTypeDef *, RS_MsgTypeDef *))</div><div class="ttdoc">Реквест мастера модбас.</div><div class="ttdef"><b>Definition</b> <a href="modbus_8c_source.html#l00136">modbus.c:136</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s_html_gad91eec9c3350f2705f1bbe1856cb0159"><div class="ttname"><a href="group___m_o_d_b_u_s___f_u_n_c_t_i_o_n_s.html#gad91eec9c3350f2705f1bbe1856cb0159">MODBUS_MODE_MASTER</a></div><div class="ttdeci">#define MODBUS_MODE_MASTER</div><div class="ttdoc">Псевдо-enum: Режим мастер</div><div class="ttdef"><b>Definition</b> <a href="modbus_8h_source.html#l00113">modbus.h:113</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s_html_ga679c526f339999281b97010876e7a295"><div class="ttname"><a href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a></div><div class="ttdeci">RS_MsgTypeDef MODBUS_MSG</div><div class="ttdoc">Default Message Struct for Modbus.</div><div class="ttdef"><b>Definition</b> <a href="modbus_8c_source.html#l00025">modbus.c:25</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___r_e_g_s___a_p_i_html_ga1f80317087624a23f84224c6f2c1d596"><div class="ttname"><a href="group___m_o_d_b_u_s___r_e_g_s___a_p_i.html#ga1f80317087624a23f84224c6f2c1d596">MB_RespGet_RegisterValue</a></div><div class="ttdeci">int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value)</div><div class="ttdoc">Получить значение регистра в ответе по его адресу</div><div class="ttdef"><b>Definition</b> <a href="modbus__master_8c_source.html#l00063">modbus_master.c:63</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___r_e_q_u_e_s_t___m_s_g_html_ga4a4798a15608f3aac04150115a628f8e"><div class="ttname"><a href="group___m_o_d_b_u_s___r_e_q_u_e_s_t___m_s_g.html#ga4a4798a15608f3aac04150115a628f8e">MB_REQUEST_READ_HOLDING_REGS</a></div><div class="ttdeci">RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)</div><div class="ttdoc">Сформировать запрос на чтение холдинг регистров</div><div class="ttdef"><b>Definition</b> <a href="modbus__master_8c_source.html#l00598">modbus_master.c:598</a></div></div>
<div class="ttc" id="astruct_r_s___handle_type_def_html"><div class="ttname"><a href="struct_r_s___handle_type_def.html">RS_HandleTypeDef</a></div><div class="ttdoc">Handle for RS communication.</div><div class="ttdef"><b>Definition</b> <a href="rs__message_8h_source.html#l00227">rs_message.h:228</a></div></div>
<div class="ttc" id="astruct_r_s___handle_type_def_html_a8bbcb263ae7a61790b559bcb55cd9aa9"><div class="ttname"><a href="struct_r_s___handle_type_def.html#a8bbcb263ae7a61790b559bcb55cd9aa9">RS_HandleTypeDef::RS_STATUS</a></div><div class="ttdeci">RS_StatusTypeDef RS_STATUS</div><div class="ttdoc">Статус RS.</div><div class="ttdef"><b>Definition</b> <a href="rs__message_8h_source.html#l00247">rs_message.h:247</a></div></div>
<div class="ttc" id="astruct_r_s___msg_type_def_html"><div class="ttname"><a href="struct_r_s___msg_type_def.html">RS_MsgTypeDef</a></div><div class="ttdoc">Structure for modbus messsage.</div><div class="ttdef"><b>Definition</b> <a href="modbus__core_8h_source.html#l00176">modbus_core.h:177</a></div></div>
</div><!-- fragment --> <h3 class="doxsection"><a class="anchor" id="autotoc_md35-настройка-карты-данных"></a>
3.5. Настройка карты данных</h3>
<p>В <span class="tt">modbus_data.h</span> настройте регистры и coils под ваше устройство:</p>
<p><b>Input Registers (только чтение)</b> </p><div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div>
<div class="line">{</div>
<div class="line"> uint16_t Temperature; <span class="comment">// Адрес 0</span></div>
<div class="line"> uint16_t Humidity; <span class="comment">// Адрес 1 </span></div>
<div class="line"> uint16_t Pressure; <span class="comment">// Адрес 2</span></div>
<div class="line"> uint16_t Voltage; <span class="comment">// Адрес 3</span></div>
<div class="line">} <a class="code hl_struct" href="struct_m_b___data_in_regs_type_def.html">MB_DataInRegsTypeDef</a>;</div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#define R_INPUT_ADDR 0 </span><span class="comment">// Начальный адрес Input регистров</span></div>
<div class="line"><span class="preprocessor">#define R_INPUT_QNT 4 </span><span class="comment">// Количество Input регистров</span></div>
<div class="ttc" id="astruct_m_b___data_in_regs_type_def_html"><div class="ttname"><a href="struct_m_b___data_in_regs_type_def.html">MB_DataInRegsTypeDef</a></div><div class="ttdoc">Регистры хранения</div><div class="ttdef"><b>Definition</b> <a href="modbus__data_8h_source.html#l00090">modbus_data.h:91</a></div></div>
</div><!-- fragment --><p> <b>Holding Registers (чтение/запись)</b> </p><div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div>
<div class="line">{</div>
<div class="line"> uint16_t SetpointTemp; <span class="comment">// Адрес 0</span></div>
<div class="line"> uint16_t SetpointHumidity; <span class="comment">// Адрес 1</span></div>
<div class="line"> uint16_t ControlMode; <span class="comment">// Адрес 2</span></div>
<div class="line">} <a class="code hl_struct" href="struct_m_b___data_hold_regs_type_def.html">MB_DataHoldRegsTypeDef</a>;</div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#define R_HOLDING_ADDR 0 </span><span class="comment">// Начальный адрес Holding регистров </span></div>
<div class="line"><span class="preprocessor">#define R_HOLDING_QNT 3 </span><span class="comment">// Количество Holding регистров</span></div>
<div class="ttc" id="astruct_m_b___data_hold_regs_type_def_html"><div class="ttname"><a href="struct_m_b___data_hold_regs_type_def.html">MB_DataHoldRegsTypeDef</a></div><div class="ttdoc">Входные регистры</div><div class="ttdef"><b>Definition</b> <a href="modbus__data_8h_source.html#l00099">modbus_data.h:100</a></div></div>
</div><!-- fragment --><p> <b>Coils (1-битные)</b> </p><div class="fragment"><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span></div>
<div class="line">{</div>
<div class="line"> <span class="keywordtype">unsigned</span> Relay1 : 1; <span class="comment">// Адрес 0</span></div>
<div class="line"> <span class="keywordtype">unsigned</span> Relay2 : 1; <span class="comment">// Адрес 1 </span></div>
<div class="line"> <span class="keywordtype">unsigned</span> Pump : 1; <span class="comment">// Адрес 2</span></div>
<div class="line"> <span class="keywordtype">unsigned</span> Heater : 1; <span class="comment">// Адрес 3</span></div>
<div class="line"> <span class="keywordtype">unsigned</span> reserved : 12; <span class="comment">// Резерв (выравнивание до 16 бит)</span></div>
<div class="line">} <a class="code hl_struct" href="struct_m_b___data_coils_type_def.html">MB_DataCoilsTypeDef</a>;</div>
<div class="line"> </div>
<div class="line"><span class="preprocessor">#define C_COILS_ADDR 0 </span><span class="comment">// Начальный адрес Coils</span></div>
<div class="line"><span class="preprocessor">#define C_COILS_QNT 4 </span><span class="comment">// Количество Coils</span></div>
<div class="ttc" id="astruct_m_b___data_coils_type_def_html"><div class="ttname"><a href="struct_m_b___data_coils_type_def.html">MB_DataCoilsTypeDef</a></div><div class="ttdoc">Коилы</div><div class="ttdef"><b>Definition</b> <a href="modbus__data_8h_source.html#l00129">modbus_data.h:130</a></div></div>
</div><!-- fragment --> <h3 class="doxsection"><a class="anchor" id="autotoc_md36-доступ-к-данным-в-коде"></a>
3.6. Доступ к данным в коде</h3>
<p>В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля </p><div class="fragment"><div class="line"><span class="comment">// Чтение входных регистров</span></div>
<div class="line">uint16_t temp = MB_DATA.InRegs.Temperature;</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Запись в регистры хранения</span></div>
<div class="line">MB_DATA.HoldRegs.SetpointTemp = 2500;</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Управление coils</span></div>
<div class="line"><a class="code hl_define" href="group___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s.html#ga635a6c4fbce49bd1e6797642b36dae7e">MB_Coil_Set_Local</a>(&amp;MB_DATA.Coils, 0); <span class="comment">// Включить Relay1</span></div>
<div class="line"><a class="code hl_define" href="group___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s.html#gabc4efb5e2a6aaa021ef5fe6c69476927">MB_Coil_Reset_Local</a>(&amp;MB_DATA.Coils, 1); <span class="comment">// Выключить Relay2</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">// Чтение coil</span></div>
<div class="line"><span class="keywordflow">if</span> (<a class="code hl_define" href="group___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s.html#ga0f8474120df77dc5f334d60d6a5f6f8f">MB_Coil_Read_Local</a>(&amp;MB_DATA.Coils, 2)) {</div>
<div class="line"> <span class="comment">// Pump включен</span></div>
<div class="line">}</div>
<div class="ttc" id="agroup___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s_html_ga0f8474120df77dc5f334d60d6a5f6f8f"><div class="ttname"><a href="group___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s.html#ga0f8474120df77dc5f334d60d6a5f6f8f">MB_Coil_Read_Local</a></div><div class="ttdeci">#define MB_Coil_Read_Local(_parr_, _coil_)</div><div class="ttdoc">Считать коил по локальному адресу.</div><div class="ttdef"><b>Definition</b> <a href="modbus__coils_8h_source.html#l00071">modbus_coils.h:71</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s_html_ga635a6c4fbce49bd1e6797642b36dae7e"><div class="ttname"><a href="group___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s.html#ga635a6c4fbce49bd1e6797642b36dae7e">MB_Coil_Set_Local</a></div><div class="ttdeci">#define MB_Coil_Set_Local(_parr_, _coil_)</div><div class="ttdoc">Выставить коил по локальному адресу.</div><div class="ttdef"><b>Definition</b> <a href="modbus__coils_8h_source.html#l00079">modbus_coils.h:79</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s_html_gabc4efb5e2a6aaa021ef5fe6c69476927"><div class="ttname"><a href="group___m_o_d_b_u_s___d_a_t_a___a_c_c_e_s_s___f_u_n_c_t_i_o_n_s.html#gabc4efb5e2a6aaa021ef5fe6c69476927">MB_Coil_Reset_Local</a></div><div class="ttdeci">#define MB_Coil_Reset_Local(_parr_, _coil_)</div><div class="ttdoc">Сбросить коил по локальному адресу.</div><div class="ttdef"><b>Definition</b> <a href="modbus__coils_8h_source.html#l00087">modbus_coils.h:87</a></div></div>
</div><!-- fragment --><p> В режиме мастера есть функции для получения информации из ответа <span class="tt">MB_RespGet_...()</span> </p><div class="fragment"><div class="line"><span class="comment">// Чтение регистров: Получить запрошенные регистры</span></div>
<div class="line">uint16_t value;</div>
<div class="line"><span class="keywordflow">if</span>(<a class="code hl_function" href="group___m_o_d_b_u_s___r_e_g_s___a_p_i.html#ga1f80317087624a23f84224c6f2c1d596">MB_RespGet_RegisterValue</a>(&amp;<a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>, 105, &amp;reg_value))</div>
<div class="line">{</div>
<div class="line"> printf(<span class="stringliteral">&quot;Register 105 value: %d\n&quot;</span>, reg_value);</div>
<div class="line">}</div>
<div class="line"><span class="comment">// Чтение коилов: Получить запрошенные коилы</span></div>
<div class="line"><span class="keywordtype">int</span> state;</div>
<div class="line"><span class="keywordflow">if</span>(<a class="code hl_function" href="group___m_o_d_b_u_s___r_e_q___c_o_i_l_s___a_p_i.html#ga643a0be1ccd587a6dfe544d9fd5ed018">MB_RespGet_CoilState</a>(&amp;<a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>, 25, &amp;coil_state))</div>
<div class="line">{</div>
<div class="line"> printf(<span class="stringliteral">&quot;Coil 25 state: %s\n&quot;</span>, coil_state ? <span class="stringliteral">&quot;ON&quot;</span> : <span class="stringliteral">&quot;OFF&quot;</span>);</div>
<div class="line">}</div>
<div class="line"><span class="comment">// Чтение диагностики: Получить запрошенныую диагностику</span></div>
<div class="line">uint16_t counter_value;</div>
<div class="line"><span class="keywordflow">if</span>(MB_RespGet_DiagnosticResponse(&amp;<a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>, &amp;counter_value))</div>
<div class="line">{</div>
<div class="line"> printf(<span class="stringliteral">&quot;Counter value: %d\n&quot;</span>, counter_value);</div>
<div class="line">}</div>
<div class="line"><span class="comment">// Чтение идентификаторов: Получить запрошенные идентификаторы</span></div>
<div class="line">uint8_t length;</div>
<div class="line"><span class="keywordtype">char</span> vendor_name[64];</div>
<div class="line"><span class="keywordflow">if</span>(<a class="code hl_function" href="group___m_o_d_b_u_s___r_e_q___d_e_f_i_d___a_p_i.html#ga0dc4119c008af34d5997eab339c437be">MB_RespGet_ObjectById</a>(&amp;<a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>, 0x00, vendor_name, &amp;length))</div>
<div class="line">{</div>
<div class="line"> printf(<span class="stringliteral">&quot;Vendor Name: %s (length: %d)\n&quot;</span>, vendor_name, length);</div>
<div class="line">} </div>
<div class="line"> </div>
<div class="line">uint8_t obj_id, obj_length;</div>
<div class="line"><span class="keywordtype">char</span> obj_data[64];</div>
<div class="line"><span class="keywordflow">if</span>(<a class="code hl_function" href="group___m_o_d_b_u_s___r_e_q___d_e_f_i_d___a_p_i.html#ga3fc5fc5abfe4f8767ccee5c11ea3d5d5">MB_RespGet_ObjectByIndex</a>(&amp;<a class="code hl_variable" href="group___m_o_d_b_u_s___m_e_s_s_a_g_e___d_e_f_i_n_e_s.html#ga679c526f339999281b97010876e7a295">MODBUS_MSG</a>, 0x00, &amp;obj_id, obj_data, &amp;obj_length))</div>
<div class="line">{</div>
<div class="line"> printf(<span class="stringliteral">&quot;First object - ID: 0x%02X, Data: %s\n&quot;</span>, obj_id, obj_data);</div>
<div class="line">} </div>
<div class="ttc" id="agroup___m_o_d_b_u_s___r_e_q___c_o_i_l_s___a_p_i_html_ga643a0be1ccd587a6dfe544d9fd5ed018"><div class="ttname"><a href="group___m_o_d_b_u_s___r_e_q___c_o_i_l_s___a_p_i.html#ga643a0be1ccd587a6dfe544d9fd5ed018">MB_RespGet_CoilState</a></div><div class="ttdeci">int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state)</div><div class="ttdoc">Получить состояние coil в ответе по его адресу</div><div class="ttdef"><b>Definition</b> <a href="modbus__master_8c_source.html#l00127">modbus_master.c:127</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___r_e_q___d_e_f_i_d___a_p_i_html_ga0dc4119c008af34d5997eab339c437be"><div class="ttname"><a href="group___m_o_d_b_u_s___r_e_q___d_e_f_i_d___a_p_i.html#ga0dc4119c008af34d5997eab339c437be">MB_RespGet_ObjectById</a></div><div class="ttdeci">int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length)</div><div class="ttdoc">Найти объект по ID в сообщении</div><div class="ttdef"><b>Definition</b> <a href="modbus__master_8c_source.html#l00193">modbus_master.c:193</a></div></div>
<div class="ttc" id="agroup___m_o_d_b_u_s___r_e_q___d_e_f_i_d___a_p_i_html_ga3fc5fc5abfe4f8767ccee5c11ea3d5d5"><div class="ttname"><a href="group___m_o_d_b_u_s___r_e_q___d_e_f_i_d___a_p_i.html#ga3fc5fc5abfe4f8767ccee5c11ea3d5d5">MB_RespGet_ObjectByIndex</a></div><div class="ttdeci">int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length)</div><div class="ttdoc">Получить объект по индексу в сообщении</div><div class="ttdef"><b>Definition</b> <a href="modbus__master_8c_source.html#l00244">modbus_master.c:244</a></div></div>
</div><!-- fragment --><h2 class="doxsection"><a class="anchor" id="autotoc_md5-обновление-библиотеки"></a>
5. <b>Обновление библиотеки</b>:</h2>
<p>После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся:</p>
<div class="fragment"><div class="line">git submodule update --remote</div>
</div><!-- fragment --> </div></div><!-- PageDoc -->
<a href="doxygen_crawl.html"></a>
</div><!-- contents -->
</div><!-- doc-content -->
</div><!-- container -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.14.0 </li>
</ul>
</div>
</body>
</html>