Modbus 0.3
Библиотека Modbus для STM
Loading...
Searching...
No Matches
modbus_master.c
Go to the documentation of this file.
1/**
2*******************************************************************************
3* @file modbus_master.c
4* @brief Модуль для реализации мастера MODBUS.
5*******************************************************************************
6* @details
7Файл содержит реализацию функций для работы Modbus в режиме мастера.
8
9@section mast Функции и макросы
10- MB_RespGet_RegisterAll() — Считать все регистра из ответа
11- MB_RespGet_RegisterValue() — Считать один регистр из ответа
12- MB_RespGet_CoilAll() — Считать все коилы из ответа
13- MB_RespGet_CoilState() — Считать один коил из ответа
14- MB_RespGet_NumberOfObjects() — Считать количество принятых объектов идентификатора
15- MB_RespGet_ObjectById() — Считать объект идентификатора по
16 его ID
17- MB_RespGet_ObjectByIndex() — Считать объект идентификатора по
18 порядковому номеру в сообщении
19- MB_RespGet_Diagnostic() — Считать запрошенный диагностический счетчик
20
21- MB_Master_Collect_Message() — Сбор сообщения в режиме мастера
22- MB_Master_Parse_Message() — Парс сообщения в режиме мастера
23******************************************************************************/
24#include "modbus.h"
25
26#ifdef MODBUS_ENABLE_MASTER
27
28
29//-------------------------------------------------------------------
30//-----------------------------FOR USER------------------------------
31/**
32 * @brief Получить значение ВСЕХ регистров в ответе
33 * @param modbus_msg Указатель на структуру сообщения
34 * @param reg_addr Адрес регистра, значение которого нужно получить
35 * @param reg_arr Указатель для массив для сохранения значений регистров
36 * @return количество считанных регистров, 0 - ошибка
37 */
38int MB_RespGet_RegisterAll(RS_MsgTypeDef *modbus_msg, uint16_t *reg_arr)
39{
40 if(modbus_msg == NULL || reg_arr == NULL)
41 return 0;
42 int read_cnt = 0;
43 int i = 0;
44 for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++)
45 {
46 if(MB_RespGet_RegisterValue(modbus_msg, addr, &reg_arr[i]))
47 {
48 read_cnt++;
49 }
50 i++;
51 }
52
53 return read_cnt;
54}
55
56/**
57 * @brief Получить значение регистра в ответе по его адресу
58 * @param modbus_msg Указатель на структуру сообщения
59 * @param reg_addr Адрес регистра, значение которого нужно получить
60 * @param reg_value Указатель для значения регистра
61 * @return 1 - успех, 0 - ошибка или reg_addr вне диапазона запроса
62 */
63int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value)
64{
65 if(modbus_msg == NULL || reg_value == NULL)
66 return 0;
67
68 // Проверяем что ответ связан с регистрами
69 if((modbus_msg->FuncCode != FC_R_DISC_IN) &&
70 (modbus_msg->FuncCode != FC_R_HOLD_REGS) &&
71 (modbus_msg->FuncCode != FC_R_IN_REGS))
72 {
73 return 0;
74 }
75
76 // Проверяем что reg_addr в пределах запрошенного диапазона
77 if(reg_addr < modbus_msg->Addr || reg_addr >= modbus_msg->Addr + modbus_msg->Qnt)
78 return 0;
79
80 // Вычисляем индекс регистра в полученных данных
81 uint16_t reg_index = reg_addr - modbus_msg->Addr;
82
83 // Проверяем что регистр существует в данных
84 if(reg_index >= modbus_msg->ByteCnt / 2)
85 return 0;
86
87 // Получаем значение регистра
88 *reg_value = modbus_msg->MbData[reg_index];
89
90 return 1;
91}
92
93
94
95/**
96 * @brief Получить состояние ВСЕХ coil в ответе
97 * @param modbus_msg Указатель на структуру сообщения
98 * @param coil_arr Указатель для массив доя сохранения состояний coil (1 - ON, 0 - OFF)
99 * @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса
100 */
101int MB_RespGet_CoilAll(RS_MsgTypeDef *modbus_msg, int *coil_arr)
102{
103 if(modbus_msg == NULL || coil_arr == NULL)
104 return 0;
105
106 int read_cnt = 0;
107 int i = 0;
108 for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++)
109 {
110 if(MB_RespGet_CoilState(modbus_msg, addr, &coil_arr[i]))
111 {
112 read_cnt++;
113 }
114 i++;
115 }
116
117 return 1;
118}
119
120/**
121 * @brief Получить состояние coil в ответе по его адресу
122 * @param modbus_msg Указатель на структуру сообщения
123 * @param coil_addr Адрес coil, состояние которого нужно получить
124 * @param coil_state Указатель для состояния coil (1 - ON, 0 - OFF)
125 * @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса
126 */
127int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state)
128{
129 if(modbus_msg == NULL || coil_state == NULL)
130 return 0;
131
132 // Проверяем что ответ связан с коилами
133 if(modbus_msg->FuncCode != FC_R_COILS)
134 {
135 return 0;
136 }
137
138 // Проверяем что coil_addr в пределах запрошенного диапазона
139 if(coil_addr < modbus_msg->Addr || coil_addr >= modbus_msg->Addr + modbus_msg->Qnt)
140 return 0;
141
142 // Вычисляем индекс coil в полученных данных
143 uint16_t coil_index = coil_addr - modbus_msg->Addr;
144
145 // Вычисляем байт и бит
146 uint8_t byte_index = coil_index / 8;
147 uint8_t data_index = coil_index / 16;
148 uint8_t bit_index = coil_index % 16;
149
150 // Проверяем что байт существует в данных
151 if(byte_index >= modbus_msg->ByteCnt)
152 return 0;
153
154 // Получаем байт и проверяем бит
155 if(bit_index < 8)
156 *coil_state = (modbus_msg->MbData[data_index] >> (bit_index+8)) & 0x01;
157 else
158 *coil_state = ((modbus_msg->MbData[data_index]&0xFF) >> (bit_index-8)) & 0x01;
159
160
161 return 1;
162}
163
164
165/**
166 * @brief Получить количество объектов в сообщении
167 * @param modbus_msg Указатель на структуру сообщения
168 * @return int Количество объектов
169 */
171{
172 if(modbus_msg == NULL)
173 {
174 return 0;
175 }
176 // Проверяем что ответ связан с диагностикой
177 if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
178 {
179 return 0;
180 }
181
182 return modbus_msg->DevId.NumbOfObj;
183}
184
185/**
186 * @brief Найти объект по ID в сообщении
187 * @param modbus_msg Указатель на структуру сообщения
188 * @param obj_id ID искомого объекта
189 * @param obj_data Буфер для данных объекта (может быть NULL)
190 * @param obj_length Указатель для длины объекта
191 * @return int Найден ли объект (1 - да, 0 - нет)
192 */
193int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length)
194{
195 if((modbus_msg == NULL) || (obj_data == NULL))
196 return 0;
197
198 // Проверяем что ответ связан с диагностикой
199 if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
200 {
201 return 0;
202 }
203
204 uint8_t *data = (uint8_t*)modbus_msg->MbData;
205 unsigned ind = 0;
206
207 for(int i = 0; i < modbus_msg->DevId.NumbOfObj; i++)
208 {
209 uint8_t current_id = data[ind++];
210 uint8_t current_length = data[ind++];
211
212 if(current_id == obj_id)
213 {
214 if(obj_length)
215 *obj_length = current_length;
216
217 for(int j = 0; j < current_length; j++)
218 {
219 obj_data[j] = data[ind++];
220 }
221 obj_data[current_length] = '\0'; // добавляем \0
222
223 return 1;
224 }
225 else
226 {
227 // Пропускаем данные этого объекта
228 ind += current_length;
229 }
230 }
231
232 return 0;
233}
234
235/**
236 * @brief Получить объект по индексу в сообщении
237 * @param modbus_msg Указатель на структуру сообщения
238 * @param index Индекс объекта (0..N-1)
239 * @param obj_id Указатель для ID объекта
240 * @param obj_data Буфер для данных объекта
241 * @param obj_length Указатель для длины объекта
242 * @return int Успешность получения (1 - получен, 0 - не найден)
243 */
244int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length)
245{
246 if((modbus_msg == NULL) || (obj_data == NULL))
247 return 0;
248
249 // Проверяем что ответ связан с диагностикой
250 if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
251 {
252 return 0;
253 }
254
255 if(index >= modbus_msg->DevId.NumbOfObj)
256 return 0;
257
258 uint8_t *data = (uint8_t*)modbus_msg->MbData;
259 unsigned ind = 0;
260
261 for(int i = 0; i <= index; i++)
262 {
263 uint8_t current_id = data[ind++];
264 uint8_t current_length = data[ind++];
265
266 if(obj_id)
267 *obj_id = current_id;
268 if(obj_length)
269 *obj_length = current_length;
270
271 if(i == index)
272 {
273 for(int j = 0; j < current_length; j++)
274 {
275 obj_data[j] = data[ind++];
276 }
277 obj_data[current_length] = '\0'; // добавляем \0
278 return 1;
279 }
280 else
281 {
282 // Пропускаем данные этого объекта
283 ind += current_length;
284 }
285 }
286
287 return 0;
288}
289
290
291/**
292 * @brief Получить данные диагностики из сообщения (MbData[1])
293 * @param modbus_msg Указатель на структуру сообщения
294 * @param data Указатель куда положить данные
295 * @return 1 - успех, 0 - ошибка
296 */
297int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data)
298{
299 if(modbus_msg == NULL || data == NULL)
300 return 0;
301
302 // Проверяем что ответ связан с диагностикой
303 if(modbus_msg->FuncCode != FC_R_DIAGNOSTICS)
304 {
305 return 0;
306 }
307
308
309
310 *data = modbus_msg->MbData[1];
311 return 1;
312}
313
314
315
316
317//-------------------------------------------------------------------
318//-----------------------------INTERNAL------------------------------
319/**
320 * @brief Определить размер модбас запроса (МАСТЕР версия).
321 * @param hRS Указатель на хендлер RS.
322 * @param rx_data_size Указатель на переменную для записи кол-ва байт для принятия.
323 * @return RS_RES Статус о корректности рассчета кол-ва байт для принятия.
324 * @details Определение сколько байтов надо принять по протоколу.
325 */
327{
328 RS_StatusTypeDef MB_RES = 0;
329 int mb_func_size = 0;
330
331
332 // Master mode - calculating response size from slave
333 if (modbus_msg->FuncCode & FC_ERR_VALUES_START)
334 {
335 // Error response: [Addr][Func|0x80][ExceptCode][CRC]
336 mb_func_size = -1; // Only Exception Code
337 }
338 else if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
339 {
340 // Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
341 mb_func_size = 1;
342 }
343 else if (modbus_msg->FuncCode == FC_R_DEVICE_ID)
344 {
345 // Device identifications: variable size, need to read first to determine
346 mb_func_size = 0; // Will be determined after reading header
347 }
348 else
349 {
350 switch (modbus_msg->FuncCode & ~FC_ERR_VALUES_START)
351 {
352 case 0x01: // Read Coils
353 case 0x02: // Read Discrete Inputs
354 case 0x03: // Read Holding Registers
355 case 0x04: // Read Input Registers
356 // Response: [ByteCount][Data...]
357 mb_func_size = modbus_msg->ByteCnt + 2; // ByteCount + variable data
358 break;
359
360 case 0x05: // Write Single Coil
361 case 0x06: // Write Single Register
362 // Echo response: [Addr][Value][CRC]
363 mb_func_size = 4; // Address(2) + Value(2)
364 break;
365
366 case 0x0F: // Write Multiple Coils
367 case 0x10: // Write Multiple Registers
368 // Echo response: [Addr][Qty][CRC]
369 mb_func_size = 4; // Address(2) + Quantity(2)
370 break;
371
372 default:
373 mb_func_size = 0;
374 }
375 }
376
377 mb_func_size = RX_FIRST_PART_SIZE + mb_func_size; // size of whole message
378 return mb_func_size;
379}
380
381/**
382 * @brief Сбор сообщения в буфер UART в режиме мастер (фрейм мастера из msg -> uart).
383 * @param hmodbus Указатель на хендлер RS.
384 * @param modbus_msg Указатель на структуру сообщения.
385 * @param modbus_uart_buff Указатель на буффер UART.
386 * @return RS_RES Статус о результате заполнения буфера.
387 */
388RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
389{
390 int ind = 0; // ind for modbus-uart buffer
391
392 //------INFO ABOUT DATA/MESSAGE------
393 //-----------[first bytes]-----------
394 // set ID of slave device
395 modbus_uart_buff[ind++] = modbus_msg->MbAddr;
396
397 // set function code
398 modbus_uart_buff[ind++] = modbus_msg->FuncCode;
399
400 if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // if no error occur
401 {
402 // fill modbus header
403 if(0) {}
404#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
405 else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications request
406 {
407 modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type;
408 modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId;
409 modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId;
410 }
411#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
412#ifdef MODBUS_ENABLE_DIAGNOSTICS
413 else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
414 {
415 // Diagnostics: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
416 modbus_uart_buff[ind++] = modbus_msg->MbData[0] >> 8; // Sub-function HI
417 modbus_uart_buff[ind++] = modbus_msg->MbData[0] & 0xFF; // Sub-function LO
418 modbus_uart_buff[ind++] = modbus_msg->MbData[1] >> 8; // Data HI
419 modbus_uart_buff[ind++] = modbus_msg->MbData[1] & 0xFF; // Data LO
420 }
421#endif //MODBUS_ENABLE_DIAGNOSTICS
422 else // classic modbus request
423 {
424 // set address
425 modbus_uart_buff[ind++] = modbus_msg->Addr >> 8;
426 modbus_uart_buff[ind++] = modbus_msg->Addr & 0xFF;
427
428 // set quantity
429 modbus_uart_buff[ind++] = modbus_msg->Qnt >> 8;
430 modbus_uart_buff[ind++] = modbus_msg->Qnt & 0xFF;
431
432 // for write multiple functions
433 if((modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10))
434 {
435 modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
436
437 // write data bytes
438 uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
439 for(int i = 0; i < modbus_msg->ByteCnt; i++)
440 {
441 modbus_uart_buff[ind++] = tmp_data_addr[i];
442 }
443 }
444 }
445 }
446
447 if(ind < 0)
448 return RS_COLLECT_MSG_ERR;
449
450 //---------------CRC----------------
451 //---------[last 2 bytes]----------
452 uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
453 modbus_msg->MbCRC = CRC_VALUE;
454 modbus_uart_buff[ind++] = CRC_VALUE & 0xFF;
455 modbus_uart_buff[ind++] = CRC_VALUE >> 8;
456
457 hmodbus->RS_Message_Size = ind;
458
459 return RS_OK;
460}
461
462/**
463 * @brief Парс сообщения в режиме мастер (фрейм слейва из uart -> msg).
464 * @param hmodbus Указатель на хендлер RS.
465 * @param modbus_msg Указатель на структуру сообщения.
466 * @param modbus_uart_buff Указатель на буффер UART.
467 * @return RS_RES Статус о результате заполнения структуры.
468 */
469RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
470{
471 int ind = 0; // ind for modbus-uart buffer
472 int expected_size = 0;
473
474 // get ID of slave device
475 modbus_msg->MbAddr = modbus_uart_buff[ind++];
476
477 // get function code (check if error response)
478 modbus_msg->FuncCode = modbus_uart_buff[ind++];
479
480 if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // error response
481 {
482 modbus_msg->Except_Code = modbus_uart_buff[ind++];
483 }
484 else if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // normal response
485 {
486 if(0) {}
487#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
488 else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications response
489 {
490 modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
491 modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
492 modbus_msg->DevId.Conformity = modbus_uart_buff[ind++];
493 modbus_msg->DevId.MoreFollows = modbus_uart_buff[ind++];
494 modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
495 modbus_msg->DevId.NumbOfObj = modbus_uart_buff[ind++];
496
497 modbus_msg->ByteCnt = 0;
498
499 // Парсинг объектов идентификации устройства
500 uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
501 int data_index = 0;
502
503 for(int obj = 0; obj < modbus_msg->DevId.NumbOfObj; obj++)
504 {
505 // Читаем ID объекта
506 uint8_t object_id = modbus_uart_buff[ind++];
507 tmp_data_addr[data_index++] = object_id;
508
509 // Читаем длину объекта
510 uint8_t object_length = modbus_uart_buff[ind++];
511 tmp_data_addr[data_index++] = object_length;
512
513 // Читаем данные объекта
514 for(int i = 0; i < object_length; i++)
515 {
516 tmp_data_addr[data_index++] = modbus_uart_buff[ind++];
517 }
518
519 modbus_msg->ByteCnt += (2 + object_length); // ID + длина + данные
520 }
521 }
522#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
523#ifdef MODBUS_ENABLE_DIAGNOSTICS
524 else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
525 {
526 // Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
527 modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8;
528 modbus_msg->MbData[0] |= modbus_uart_buff[ind++];
529 modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8;
530 modbus_msg->MbData[1] |= modbus_uart_buff[ind++];
531 }
532#endif //MODBUS_ENABLE_DIAGNOSTICS
533 else // classic modbus response
534 {
535 // get byte count for read functions
536 if((modbus_msg->FuncCode == 0x01) || (modbus_msg->FuncCode == 0x02) ||
537 (modbus_msg->FuncCode == 0x03) || (modbus_msg->FuncCode == 0x04))
538 {
539 modbus_msg->ByteCnt = modbus_uart_buff[ind++];
540
541 // read data bytes
542 uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
543 for(int i = 0; i < modbus_msg->ByteCnt; i++)
544 {
545 if(i % 2 == 0) // HI byte
546 tmp_data_addr[i/2] = (uint16_t)modbus_uart_buff[ind++] << 8;
547 else // LO byte
548 tmp_data_addr[i/2] |= modbus_uart_buff[ind++];
549 }
550 }
551 // for write functions - echo address and quantity
552 else if((modbus_msg->FuncCode == 0x05) || (modbus_msg->FuncCode == 0x06) ||
553 (modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10))
554 {
555 modbus_msg->Addr = modbus_uart_buff[ind++] << 8;
556 modbus_msg->Addr |= modbus_uart_buff[ind++];
557 modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
558 modbus_msg->Qnt |= modbus_uart_buff[ind++];
559 }
560 }
561 }
562
563
564 //---------------CRC----------------
565 //----------[last 2 bytes]----------
566 uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
567 modbus_msg->MbCRC = modbus_uart_buff[ind++];
568 modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8;
569
570 if(modbus_msg->MbCRC != CRC_VALUE)
571 {
572 TrackerCnt_Err(hmodbus->rs_err);
573 return RS_PARSE_MSG_ERR;
574 }
575
576 return RS_OK;
577}
578
579
580
581
582
583/** @brief Сформировать запрос на чтение коилов */
584RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
585{
586 RS_MsgTypeDef msg = {slave_addr, FC_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0};
587 return msg;
588}
589
590/** @brief Сформировать запрос на чтение дискретных регистров */
591RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
592{
593 RS_MsgTypeDef msg = {slave_addr, FC_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0};
594 return msg;
595}
596
597/** @brief Сформировать запрос на чтение холдинг регистров */
598RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
599{
600 RS_MsgTypeDef msg = {slave_addr, FC_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
601 return msg;
602}
603
604/** @brief Сформировать запрос на чтение инпут регистров */
605RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
606{
607 RS_MsgTypeDef msg = {slave_addr, FC_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
608 return msg;
609}
610
611/** @brief Сформировать запрос на запись одного коила */
612RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value)
613{
614 RS_MsgTypeDef msg = {slave_addr, FC_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0};
615 return msg;
616}
617
618/** @brief Сформировать запрос на запись одного регистра */
619RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value)
620{
621 RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0};
622 return msg;
623}
624
625/** @brief Сформировать запрос на запись нескольких регистров */
626RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data)
627{
628 RS_MsgTypeDef msg = {slave_addr, FC_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0};
629
630 // Calculate byte count and prepare data
631 uint8_t byte_count = (quantity + 7) / 8;
632 msg.ByteCnt = byte_count;
633
634 // Copy coil data to message MbData array
635 for(int i = 0; i < byte_count; i++) {
636 if(i < DATA_SIZE) {
637 msg.MbData[i] = coils_data[i];
638 }
639 }
640
641 return msg;
642}
643
644/** @brief Сформировать запрос на запись нескольких коилов */
645RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data)
646{
647 RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
648
649 msg.ByteCnt = quantity * 2; // Each register is 2 bytes
650
651 // Copy register data to message MbData array
652 for(int i = 0; i < quantity && i < DATA_SIZE; i++) {
653 msg.MbData[i] = regs_data[i];
654 }
655
656 return msg;
657}
658
659//---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ-----------
660RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data)
661{
662 RS_MsgTypeDef msg = {slave_addr, FC_R_DIAGNOSTICS, {0}, 0, 0, 0, {sub_function, data}, 0, 0};
663 return msg;
664}
665RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr)
666{
667 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0000, 0x0000);
668}
669
670RS_MsgTypeDef MB_REQUEST_RESTART_COMMUNICATIONS(uint8_t slave_addr, uint16_t data)
671{
672 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0001, data);
673}
674
675RS_MsgTypeDef MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(uint8_t slave_addr)
676{
677 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0002, 0x0000);
678}
679
680RS_MsgTypeDef MB_REQUEST_FORCE_LISTEN_ONLY_MODE(uint8_t slave_addr)
681{
682 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0004, 0x0000);
683}
684
685RS_MsgTypeDef MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(uint8_t slave_addr)
686{
687 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000A, 0x0000);
688}
689
690RS_MsgTypeDef MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(uint8_t slave_addr)
691{
692 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000B, 0x0000);
693}
694
695RS_MsgTypeDef MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(uint8_t slave_addr)
696{
697 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000C, 0x0000);
698}
699
700RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(uint8_t slave_addr)
701{
702 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000D, 0x0000);
703}
704
705RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(uint8_t slave_addr)
706{
707 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000E, 0x0000);
708}
709
710RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(uint8_t slave_addr)
711{
712 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000F, 0x0000);
713}
714
715RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NAK_COUNT(uint8_t slave_addr)
716{
717 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0010, 0x0000);
718}
719
720RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(uint8_t slave_addr)
721{
722 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0011, 0x0000);
723}
724
725RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr)
726{
727 return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0012, 0x0000);
728}
729
730//---------ИДЕНТИФИКАТОРЫ МОДБАС-----------
731RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr)
732{
733 RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
734 return msg;
735}
736
737RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr)
738{
739 RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
740 return msg;
741}
742
743RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr)
744{
745 RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
746 return msg;
747}
748
749RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id)
750{
751 RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
752 return msg;
753}
754
755#endif //MODBUS_ENABLE_MASTER
RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
Сбор сообщения в буфер UART в режиме мастер (фрейм мастера из msg -> uart).
RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
Парс сообщения в режиме мастер (фрейм слейва из uart -> msg).
#define RX_FIRST_PART_SIZE
Size of first part of message that will be received first receive info part of message,...
Definition modbus_core.h:66
#define FC_ERR_VALUES_START
from this value starts error func codes
Definition modbus_core.h:88
#define DATA_SIZE
maximum number of data: DWORD (NOT MESSAGE SIZE)
Definition modbus_core.h:53
@ FC_W_HOLD_REG
Запись одиночного регистра
@ FC_R_DEVICE_ID
Чтение информации об устройстве
@ FC_R_COILS
Чтение битовых ячеек
Definition modbus_core.h:97
@ FC_R_DISC_IN
Чтение дискретных входов
Definition modbus_core.h:98
@ FC_W_COILS
Запись нескольких битовых ячеек
@ FC_R_IN_REGS
Чтение регистров хранения
@ FC_W_COIL
Запись битовой ячейки
@ FC_R_DIAGNOSTICS
Чтение диагностической информации устройства
@ FC_R_HOLD_REGS
Чтение входных регистров
@ FC_W_HOLD_REGS
Запись нескольких регистров
int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value)
Получить значение регистра в ответе по его адресу
int MB_RespGet_RegisterAll(RS_MsgTypeDef *modbus_msg, uint16_t *reg_arr)
Получить значение ВСЕХ регистров в ответе
int MB_RespGet_CoilAll(RS_MsgTypeDef *modbus_msg, int *coil_arr)
Получить состояние ВСЕХ coil в ответе
int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state)
Получить состояние coil в ответе по его адресу
int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length)
Найти объект по ID в сообщении
int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg)
Получить количество объектов в сообщении
int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length)
Получить объект по индексу в сообщении
int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data)
Получить данные диагностики из сообщения (MbData[1])
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value)
Сформировать запрос на запись одного регистра
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value)
Сформировать запрос на запись одного коила
RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
Сформировать запрос на чтение холдинг регистров
RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
Сформировать запрос на чтение инпут регистров
RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
Сформировать запрос на чтение дискретных регистров
RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data)
Сформировать запрос на запись нескольких регистров
RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data)
Сформировать запрос на запись нескольких коилов
RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
Сформировать запрос на чтение коилов
#define TrackerCnt_Err(_cntstruct_)
Инкрементировать переменную - ошибок
Definition rs_message.h:108
RS_StatusTypeDef
Enums for respond CMD about RS status.
Definition rs_message.h:164
Главный заголовочный файл Modbus библиотеки
static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
Определить размер модбас запроса (МАСТЕР версия).
uint8_t Conformity
Identification conformity level of the device and type of supported access MODBUS_DEVICE_CONFORMITY.
MB_MEITypeDef MEI_Type
MEI Type assigned number for Device Identifications Interface.
Handle for RS communication.
Definition rs_message.h:228
int32_t RS_Message_Size
size of whole message, not only data
Definition rs_message.h:233
Structure for modbus messsage.
MB_FunctonTypeDef FuncCode
Modbus Function Code.
uint16_t Qnt
Quantity of modbus data.
uint8_t MbAddr
Modbus Slave Address.
MB_ExceptionTypeDef Except_Code
Exception Code for the command.
uint16_t MbCRC
Modbus CRC.
MB_DevIdMsgTypeDef DevId
Read Device Identifications Header struct.
uint8_t ByteCnt
Quantity of bytes of data in message to transmit/receive.
uint16_t MbData[DATA_SIZE]
Modbus Data.
uint16_t Addr
Modbus Address of data.