Modbus 0.3
Библиотека Modbus для STM
Loading...
Searching...
No Matches
modbus_diag.c
Go to the documentation of this file.
1/**
2*******************************************************************************
3* @file modbus_diag.c
4* @brief Реализация диагностики устройства Modbus
5*******************************************************************************
6* @details
7Модуль обработки запросов диагностической информации (0x08):
8- Полная поддержка всех подфункций диагностики согласно спецификации Modbus
9- Выставление любого бита в Diagnostics Register
10- Сбор статистики работы устройства
11- Управление режимами работы (Normal/Listen Only)
12******************************************************************************/
13#include "modbus_diag.h"
14
15#ifdef MODBUS_ENABLE_DIAGNOSTICS
16
17MB_DiagnosticsInfoTypeDef MB_DIAG = {0}; ///< Глобальная структура диагностики
18
19/**
20 * @brief Инициализация диагностических счетчиков
21 */
23{
24 MB_DIAG.DiagnosticRegister = 0;
25 MB_DIAG.DeviceMode = MODBUS_NORMAL_MODE;
26
27 // Инициализация счетчиков
28 MB_DIAG.Counters.BusMessage = 0;
29 MB_DIAG.Counters.BusCommunicationErr = 0;
30 MB_DIAG.Counters.BusExceptionErr = 0;
31 MB_DIAG.Counters.SlaveMessage = 0;
32 MB_DIAG.Counters.SlaveNoResponse = 0;
33 MB_DIAG.Counters.SlaveNAK = 0;
34 MB_DIAG.Counters.SlaveBusy = 0;
35 MB_DIAG.Counters.BusCharacterOverrun = 0;
36}
37
38
39/**
40 * @brief Выставить бит в регистре диагностике
41 * @param bit_num Номер бита для выставления (1-15, 0 бит нельзя выставить)
42 * @param bit_state Состояние бита для выставления (Выставить/Сбросить)
43 * @return >0 - номер выставленного бита, 0 - ошибка
44 */
45int MB_Diagnostics_WriteBit(int bit_num, int bit_state)
46{
47 if(bit_num == 0 || bit_num > 15)
48 return 0;
49
50 if(bit_state)
51 MB_DIAG.DiagnosticRegister |= (1 << bit_num);
52 else
53 MB_DIAG.DiagnosticRegister &= ~(1 << bit_num);
54
55 return bit_num;
56}
57/**
58 * @brief Прочитать состояние бита диагностического регистра
59 * @param bit_num Номер бита (0-15)
60 * @return 1 - бит установлен, 0 - бит сброшен или ошибка
61 */
62int MB_Diagnostics_GetBit(int bit_num)
63{
64 if(bit_num < 0 || bit_num > 15)
65 return 0;
66
67 return (MB_DIAG.DiagnosticRegister >> bit_num) & 0x01;
68}
69
70/**
71 * @brief Обработать функцию Diagnostics (Serial Line only) (0x08)
72 * @param modbus_msg Указатель на структуру сообщения modbus
73 * @return fMessageHandled Статус обработки команды
74 */
76{
77 uint16_t sub_function = modbus_msg->MbData[0];
78 uint16_t request_data = modbus_msg->MbData[1];
79
80 // Если устройство в режиме Listen Only, отвечаем только на sub-function 0x01
81 if (MB_DIAG.DeviceMode == MODBUS_LISTEN_ONLY_MODE && sub_function != 0x0001)
82 {
83 return 0; // Не отвечаем в режиме Listen Only
84 }
85
86 switch(sub_function)
87 {
88 case 0x0000: // Return Query Data
89 // Эхо-ответ с теми же данными
90 modbus_msg->MbData[0] = sub_function;
91 modbus_msg->MbData[1] = request_data;
92 modbus_msg->ByteCnt = 4;
93 break;
94
95 case 0x0001: // Restart Communications
96 // Перезапуск коммуникаций - выходим из Listen Only режима
97 MB_DIAG.DeviceMode = MODBUS_NORMAL_MODE;
98
99 // Если request_data = 0xFF00, очищаем лог событий
100 if (request_data == 0xFF00)
101 {
102 MB_DiagnosticsInit(); // Полный сброс
103 }
104 else
105 {
106 // Очищаем только счетчики, но не регистр диагностики
107 MB_DIAG.Counters.BusMessage = 0;
108 MB_DIAG.Counters.BusCommunicationErr = 0;
109 MB_DIAG.Counters.BusExceptionErr = 0;
110 MB_DIAG.Counters.SlaveMessage = 0;
111 MB_DIAG.Counters.SlaveNoResponse = 0;
112 MB_DIAG.Counters.SlaveNAK = 0;
113 MB_DIAG.Counters.SlaveBusy = 0;
114 MB_DIAG.Counters.BusCharacterOverrun = 0;
115 }
116
117 modbus_msg->MbData[0] = sub_function;
118 modbus_msg->MbData[1] = request_data;
119 modbus_msg->ByteCnt = 4;
120 break;
121
122 case 0x0002: // Return Diagnostic Register
123 modbus_msg->MbData[0] = sub_function;
124 modbus_msg->MbData[1] = MB_DIAG.DiagnosticRegister;
125 modbus_msg->ByteCnt = 4;
126 break;
127
128 case 0x0003: // Change ASCII Input Delimiter
129 // В RTU режиме не поддерживается
130 modbus_msg->FuncCode |= FC_ERR_VALUES_START;
131 modbus_msg->Except_Code = ET_ILLEGAL_FUNCTION;
132 return 0;
133
134 case 0x0004: // Force Listen Only Mode
135 MB_DIAG.DeviceMode = MODBUS_LISTEN_ONLY_MODE;
136 // В режиме Listen Only не отправляем ответ
137 return 0;
138
139 case 0x000A: // Clear Counters and Diagnostic Register
140 MB_DiagnosticsInit(); // Полный сброс
141 modbus_msg->MbData[0] = sub_function;
142 modbus_msg->MbData[1] = 0;
143 modbus_msg->ByteCnt = 4;
144 break;
145
146 case 0x000B: // Return Bus Message Count
147 modbus_msg->MbData[0] = sub_function;
148 modbus_msg->MbData[1] = MB_DIAG.Counters.BusMessage;
149 modbus_msg->ByteCnt = 4;
150 break;
151
152 case 0x000C: // Return Bus Communication Error Count
153 modbus_msg->MbData[0] = sub_function;
154 modbus_msg->MbData[1] = MB_DIAG.Counters.BusCommunicationErr;
155 modbus_msg->ByteCnt = 4;
156 break;
157
158 case 0x000D: // Return Bus Exception Error Count
159 modbus_msg->MbData[0] = sub_function;
160 modbus_msg->MbData[1] = MB_DIAG.Counters.BusExceptionErr;
161 modbus_msg->ByteCnt = 4;
162 break;
163
164 case 0x000E: // Return Server Message Count
165 modbus_msg->MbData[0] = sub_function;
166 modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveMessage;
167 modbus_msg->ByteCnt = 4;
168 break;
169
170 case 0x000F: // Return Slave No Response Count
171 modbus_msg->MbData[0] = sub_function;
172 modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveNoResponse;
173 modbus_msg->ByteCnt = 4;
174 break;
175
176 case 0x0010: // Return Slave NAK Count
177 modbus_msg->MbData[0] = sub_function;
178 modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveNAK;
179 modbus_msg->ByteCnt = 4;
180 break;
181
182 case 0x0011: // Return Slave Busy Count
183 modbus_msg->MbData[0] = sub_function;
184 modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveBusy;
185 modbus_msg->ByteCnt = 4;
186 break;
187
188 case 0x0012: // Return Bus Character Overrun Count
189 modbus_msg->MbData[0] = sub_function;
190 modbus_msg->MbData[1] = MB_DIAG.Counters.BusCharacterOverrun;
191 modbus_msg->ByteCnt = 4;
192 break;
193
194 case 0x0014: // Clear Overrun Counter and Flag
195 MB_DIAG.Counters.BusCharacterOverrun = 0;
196 // Сбрасываем флаг переполнения в DiagnosticRegister
197 MB_DIAG.DiagnosticRegister &= ~(1<<0);
198 modbus_msg->MbData[0] = sub_function;
199 modbus_msg->MbData[1] = 0;
200 modbus_msg->ByteCnt = 4;
201 break;
202
203 default:
204 modbus_msg->FuncCode |= FC_ERR_VALUES_START;
205 modbus_msg->Except_Code = ET_ILLEGAL_FUNCTION;
206 return 0;
207 }
208
209 return 1;
210}
211
212/**
213 * @brief Увеличивает счетчик сообщений на шине
214 */
216{
217 MB_DIAG.Counters.BusMessage++;
218}
219
220/**
221 * @brief Увеличивает счетчик ошибок связи
222 */
224{
225 if (MB_DIAG.Counters.BusCommunicationErr < 0xFFFF)
226 MB_DIAG.Counters.BusCommunicationErr++;
227}
228
229/**
230 * @brief Увеличивает счетчик исключений
231 */
233{
234 if (MB_DIAG.Counters.BusExceptionErr < 0xFFFF)
235 MB_DIAG.Counters.BusExceptionErr++;
236}
237
238/**
239 * @brief Увеличивает счетчик переполнения символов
240 */
242{
243 if (MB_DIAG.Counters.BusCharacterOverrun < 0xFFFF)
244 {
245 MB_DIAG.Counters.BusCharacterOverrun++;
246 // Устанавливаем флаг переполнения в DiagnosticRegister
247 MB_DIAG.DiagnosticRegister |= (1 << 0);
248 }
249}
250
251/**
252 * @brief Увеличивает счетчик отсутствия ответов
253 */
255{
256 if (MB_DIAG.Counters.SlaveMessage < 0xFFFF)
257 MB_DIAG.Counters.SlaveMessage++;
258}
259
260/**
261 * @brief Увеличивает счетчик отсутствия ответов
262 */
264{
265 if (MB_DIAG.Counters.SlaveNoResponse < 0xFFFF)
266 MB_DIAG.Counters.SlaveNoResponse++;
267}
268
269/**
270 * @brief Увеличивает счетчик NAK ответов
271 */
273{
274 if (MB_DIAG.Counters.SlaveNAK < 0xFFFF)
275 MB_DIAG.Counters.SlaveNAK++;
276}
277
278/**
279 * @brief Увеличивает счетчик занятости устройства
280 */
282{
283 if (MB_DIAG.Counters.SlaveBusy < 0xFFFF)
284 MB_DIAG.Counters.SlaveBusy++;
285}
286
287/**
288 * @brief Получение текущего режима устройства
289 * @return Текущий режим работы устройства
290 */
292{
293 return MB_DIAG.DeviceMode;
294}
295
296#endif //MODBUS_ENABLE_DIAGNOSTICS
uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg)
Обработать функцию Diagnostics (Serial Line only) (0x08)
Definition modbus_diag.c:75
void MB_Diagnostics_CommunicationErrorCnt(void)
Увеличивает счетчик ошибок связи
void MB_Diagnostics_SlaveMessageCnt(void)
Увеличивает счетчик отсутствия ответов
void MB_Diagnostics_SlaveNAKCnt(void)
Увеличивает счетчик NAK ответов
void MB_Diagnostics_SlaveBusyCnt(void)
Увеличивает счетчик занятости устройства
int MB_Diagnostics_GetBit(int bit_num)
Прочитать состояние бита диагностического регистра
Definition modbus_diag.c:62
void MB_Diagnostics_ExceptionErrorCnt(void)
Увеличивает счетчик исключений
int MB_Diagnostics_WriteBit(int bit_num, int bit_state)
Выставить бит в регистре диагностике
Definition modbus_diag.c:45
void MB_Diagnostics_SlaveNoResponseCnt(void)
Увеличивает счетчик отсутствия ответов
void MB_Diagnostics_BusMessageCnt(void)
Увеличивает счетчик сообщений на шине
MB_DeviceModeTypeDef MB_GetDeviceMode(void)
Получение текущего режима устройства
void MB_Diagnostics_CharacterOverrunCnt(void)
Увеличивает счетчик переполнения символов
MB_DiagnosticsInfoTypeDef MB_DIAG
Глобальная структура диагностики
Definition modbus_diag.c:17
void MB_DiagnosticsInit(void)
Инициализация диагностических счетчиков
Definition modbus_diag.c:22
MB_DeviceModeTypeDef
Режимы работы устройства
Definition modbus_diag.h:31
#define FC_ERR_VALUES_START
from this value starts error func codes
Definition modbus_core.h:88
@ ET_ILLEGAL_FUNCTION
Принятый код функции не может быть обработан
Definition modbus_core.h:79
Диагностика устройства Modbus.
Структура со диагностической информацией устройства модбас
Definition modbus_diag.h:39
Structure for modbus messsage.
MB_FunctonTypeDef FuncCode
Modbus Function Code.
MB_ExceptionTypeDef Except_Code
Exception Code for the command.
uint8_t ByteCnt
Quantity of bytes of data in message to transmit/receive.
uint16_t MbData[DATA_SIZE]
Modbus Data.