Files
UKSI_TEST/AllLibs/Modbus/Src/modbus_master.c
2025-12-16 17:57:59 +03:00

756 lines
26 KiB
C
Raw Permalink 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.
/**
*******************************************************************************
* @file modbus_master.c
* @brief Модуль для реализации мастера MODBUS.
*******************************************************************************
* @details
Файл содержит реализацию функций для работы Modbus в режиме мастера.
@section mast Функции и макросы
- MB_RespGet_RegisterAll() — Считать все регистра из ответа
- MB_RespGet_RegisterValue() — Считать один регистр из ответа
- MB_RespGet_CoilAll() — Считать все коилы из ответа
- MB_RespGet_CoilState() — Считать один коил из ответа
- MB_RespGet_NumberOfObjects() — Считать количество принятых объектов идентификатора
- MB_RespGet_ObjectById() — Считать объект идентификатора по
его ID
- MB_RespGet_ObjectByIndex() — Считать объект идентификатора по
порядковому номеру в сообщении
- MB_RespGet_Diagnostic() — Считать запрошенный диагностический счетчик
- MB_Master_Collect_Message() — Сбор сообщения в режиме мастера
- MB_Master_Parse_Message() — Парс сообщения в режиме мастера
******************************************************************************/
#include "modbus.h"
#ifdef MODBUS_ENABLE_MASTER
//-------------------------------------------------------------------
//-----------------------------FOR USER------------------------------
/**
* @brief Получить значение ВСЕХ регистров в ответе
* @param modbus_msg Указатель на структуру сообщения
* @param reg_addr Адрес регистра, значение которого нужно получить
* @param reg_arr Указатель для массив для сохранения значений регистров
* @return количество считанных регистров, 0 - ошибка
*/
int MB_RespGet_RegisterAll(RS_MsgTypeDef *modbus_msg, uint16_t *reg_arr)
{
if(modbus_msg == NULL || reg_arr == NULL)
return 0;
int read_cnt = 0;
int i = 0;
for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++)
{
if(MB_RespGet_RegisterValue(modbus_msg, addr, &reg_arr[i]))
{
read_cnt++;
}
i++;
}
return read_cnt;
}
/**
* @brief Получить значение регистра в ответе по его адресу
* @param modbus_msg Указатель на структуру сообщения
* @param reg_addr Адрес регистра, значение которого нужно получить
* @param reg_value Указатель для значения регистра
* @return 1 - успех, 0 - ошибка или reg_addr вне диапазона запроса
*/
int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value)
{
if(modbus_msg == NULL || reg_value == NULL)
return 0;
// Проверяем что ответ связан с регистрами
if((modbus_msg->FuncCode != FC_R_DISC_IN) &&
(modbus_msg->FuncCode != FC_R_HOLD_REGS) &&
(modbus_msg->FuncCode != FC_R_IN_REGS))
{
return 0;
}
// Проверяем что reg_addr в пределах запрошенного диапазона
if(reg_addr < modbus_msg->Addr || reg_addr >= modbus_msg->Addr + modbus_msg->Qnt)
return 0;
// Вычисляем индекс регистра в полученных данных
uint16_t reg_index = reg_addr - modbus_msg->Addr;
// Проверяем что регистр существует в данных
if(reg_index >= modbus_msg->ByteCnt / 2)
return 0;
// Получаем значение регистра
*reg_value = modbus_msg->MbData[reg_index];
return 1;
}
/**
* @brief Получить состояние ВСЕХ coil в ответе
* @param modbus_msg Указатель на структуру сообщения
* @param coil_arr Указатель для массив доя сохранения состояний coil (1 - ON, 0 - OFF)
* @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса
*/
int MB_RespGet_CoilAll(RS_MsgTypeDef *modbus_msg, int *coil_arr)
{
if(modbus_msg == NULL || coil_arr == NULL)
return 0;
int read_cnt = 0;
int i = 0;
for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++)
{
if(MB_RespGet_CoilState(modbus_msg, addr, &coil_arr[i]))
{
read_cnt++;
}
i++;
}
return 1;
}
/**
* @brief Получить состояние coil в ответе по его адресу
* @param modbus_msg Указатель на структуру сообщения
* @param coil_addr Адрес coil, состояние которого нужно получить
* @param coil_state Указатель для состояния coil (1 - ON, 0 - OFF)
* @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса
*/
int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state)
{
if(modbus_msg == NULL || coil_state == NULL)
return 0;
// Проверяем что ответ связан с коилами
if(modbus_msg->FuncCode != FC_R_COILS)
{
return 0;
}
// Проверяем что coil_addr в пределах запрошенного диапазона
if(coil_addr < modbus_msg->Addr || coil_addr >= modbus_msg->Addr + modbus_msg->Qnt)
return 0;
// Вычисляем индекс coil в полученных данных
uint16_t coil_index = coil_addr - modbus_msg->Addr;
// Вычисляем байт и бит
uint8_t byte_index = coil_index / 8;
uint8_t data_index = coil_index / 16;
uint8_t bit_index = coil_index % 16;
// Проверяем что байт существует в данных
if(byte_index >= modbus_msg->ByteCnt)
return 0;
// Получаем байт и проверяем бит
if(bit_index < 8)
*coil_state = (modbus_msg->MbData[data_index] >> (bit_index+8)) & 0x01;
else
*coil_state = ((modbus_msg->MbData[data_index]&0xFF) >> (bit_index-8)) & 0x01;
return 1;
}
/**
* @brief Получить количество объектов в сообщении
* @param modbus_msg Указатель на структуру сообщения
* @return int Количество объектов
*/
int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg)
{
if(modbus_msg == NULL)
{
return 0;
}
// Проверяем что ответ связан с диагностикой
if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
{
return 0;
}
return modbus_msg->DevId.NumbOfObj;
}
/**
* @brief Найти объект по ID в сообщении
* @param modbus_msg Указатель на структуру сообщения
* @param obj_id ID искомого объекта
* @param obj_data Буфер для данных объекта (может быть NULL)
* @param obj_length Указатель для длины объекта
* @return int Найден ли объект (1 - да, 0 - нет)
*/
int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length)
{
if((modbus_msg == NULL) || (obj_data == NULL))
return 0;
// Проверяем что ответ связан с диагностикой
if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
{
return 0;
}
uint8_t *data = (uint8_t*)modbus_msg->MbData;
unsigned ind = 0;
for(int i = 0; i < modbus_msg->DevId.NumbOfObj; i++)
{
uint8_t current_id = data[ind++];
uint8_t current_length = data[ind++];
if(current_id == obj_id)
{
if(obj_length)
*obj_length = current_length;
for(int j = 0; j < current_length; j++)
{
obj_data[j] = data[ind++];
}
obj_data[current_length] = '\0'; // добавляем \0
return 1;
}
else
{
// Пропускаем данные этого объекта
ind += current_length;
}
}
return 0;
}
/**
* @brief Получить объект по индексу в сообщении
* @param modbus_msg Указатель на структуру сообщения
* @param index Индекс объекта (0..N-1)
* @param obj_id Указатель для ID объекта
* @param obj_data Буфер для данных объекта
* @param obj_length Указатель для длины объекта
* @return int Успешность получения (1 - получен, 0 - не найден)
*/
int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length)
{
if((modbus_msg == NULL) || (obj_data == NULL))
return 0;
// Проверяем что ответ связан с диагностикой
if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
{
return 0;
}
if(index >= modbus_msg->DevId.NumbOfObj)
return 0;
uint8_t *data = (uint8_t*)modbus_msg->MbData;
unsigned ind = 0;
for(int i = 0; i <= index; i++)
{
uint8_t current_id = data[ind++];
uint8_t current_length = data[ind++];
if(obj_id)
*obj_id = current_id;
if(obj_length)
*obj_length = current_length;
if(i == index)
{
for(int j = 0; j < current_length; j++)
{
obj_data[j] = data[ind++];
}
obj_data[current_length] = '\0'; // добавляем \0
return 1;
}
else
{
// Пропускаем данные этого объекта
ind += current_length;
}
}
return 0;
}
/**
* @brief Получить данные диагностики из сообщения (MbData[1])
* @param modbus_msg Указатель на структуру сообщения
* @param data Указатель куда положить данные
* @return 1 - успех, 0 - ошибка
*/
int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data)
{
if(modbus_msg == NULL || data == NULL)
return 0;
// Проверяем что ответ связан с диагностикой
if(modbus_msg->FuncCode != FC_R_DIAGNOSTICS)
{
return 0;
}
*data = modbus_msg->MbData[1];
return 1;
}
//-------------------------------------------------------------------
//-----------------------------INTERNAL------------------------------
/**
* @brief Определить размер модбас запроса (МАСТЕР версия).
* @param hRS Указатель на хендлер RS.
* @param rx_data_size Указатель на переменную для записи кол-ва байт для принятия.
* @return RS_RES Статус о корректности рассчета кол-ва байт для принятия.
* @details Определение сколько байтов надо принять по протоколу.
*/
static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
{
RS_StatusTypeDef MB_RES = 0;
int mb_func_size = 0;
// Master mode - calculating response size from slave
if (modbus_msg->FuncCode & FC_ERR_VALUES_START)
{
// Error response: [Addr][Func|0x80][ExceptCode][CRC]
mb_func_size = -1; // Only Exception Code
}
else if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{
// Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
mb_func_size = 1;
}
else if (modbus_msg->FuncCode == FC_R_DEVICE_ID)
{
// Device identifications: variable size, need to read first to determine
mb_func_size = 0; // Will be determined after reading header
}
else
{
switch (modbus_msg->FuncCode & ~FC_ERR_VALUES_START)
{
case 0x01: // Read Coils
case 0x02: // Read Discrete Inputs
case 0x03: // Read Holding Registers
case 0x04: // Read Input Registers
// Response: [ByteCount][Data...]
mb_func_size = modbus_msg->ByteCnt + 2; // ByteCount + variable data
break;
case 0x05: // Write Single Coil
case 0x06: // Write Single Register
// Echo response: [Addr][Value][CRC]
mb_func_size = 4; // Address(2) + Value(2)
break;
case 0x0F: // Write Multiple Coils
case 0x10: // Write Multiple Registers
// Echo response: [Addr][Qty][CRC]
mb_func_size = 4; // Address(2) + Quantity(2)
break;
default:
mb_func_size = 0;
}
}
mb_func_size = RS_RX_FIRST_PART_SIZE + mb_func_size; // size of whole message
return mb_func_size;
}
/**
* @brief Сбор сообщения в буфер UART в режиме мастер (фрейм мастера из msg -> uart).
* @param hmodbus Указатель на хендлер RS.
* @param modbus_msg Указатель на структуру сообщения.
* @param modbus_uart_buff Указатель на буффер UART.
* @return RS_RES Статус о результате заполнения буфера.
*/
RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
{
int ind = 0; // ind for modbus-uart buffer
//------INFO ABOUT DATA/MESSAGE------
//-----------[first bytes]-----------
// set ID of slave device
modbus_uart_buff[ind++] = modbus_msg->DeviceAddr;
// set function code
modbus_uart_buff[ind++] = modbus_msg->FuncCode;
if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // if no error occur
{
// fill modbus header
if(0) {}
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications request
{
modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type;
modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId;
modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId;
}
#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#ifdef MODBUS_ENABLE_DIAGNOSTICS
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{
// Diagnostics: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
modbus_uart_buff[ind++] = modbus_msg->MbData[0] >> 8; // Sub-function HI
modbus_uart_buff[ind++] = modbus_msg->MbData[0] & 0xFF; // Sub-function LO
modbus_uart_buff[ind++] = modbus_msg->MbData[1] >> 8; // Data HI
modbus_uart_buff[ind++] = modbus_msg->MbData[1] & 0xFF; // Data LO
}
#endif //MODBUS_ENABLE_DIAGNOSTICS
else // classic modbus request
{
// set address
modbus_uart_buff[ind++] = modbus_msg->Addr >> 8;
modbus_uart_buff[ind++] = modbus_msg->Addr & 0xFF;
// set quantity
modbus_uart_buff[ind++] = modbus_msg->Qnt >> 8;
modbus_uart_buff[ind++] = modbus_msg->Qnt & 0xFF;
// for write multiple functions
if((modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10))
{
modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
// write data bytes
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++)
{
modbus_uart_buff[ind++] = tmp_data_addr[i];
}
}
}
}
if(ind < 0)
return RS_COLLECT_MSG_ERR;
//---------------CRC----------------
//---------[last 2 bytes]----------
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
modbus_msg->MbCRC = CRC_VALUE;
modbus_uart_buff[ind++] = CRC_VALUE & 0xFF;
modbus_uart_buff[ind++] = CRC_VALUE >> 8;
hmodbus->RS_Message_Size = ind;
return RS_OK;
}
/**
* @brief Парс сообщения в режиме мастер (фрейм слейва из uart -> msg).
* @param hmodbus Указатель на хендлер RS.
* @param modbus_msg Указатель на структуру сообщения.
* @param modbus_uart_buff Указатель на буффер UART.
* @return RS_RES Статус о результате заполнения структуры.
*/
RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
{
int ind = 0; // ind for modbus-uart buffer
int expected_size = 0;
// get ID of slave device
modbus_msg->DeviceAddr = modbus_uart_buff[ind++];
// get function code (check if error response)
modbus_msg->FuncCode = modbus_uart_buff[ind++];
if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // error response
{
modbus_msg->Except_Code = modbus_uart_buff[ind++];
}
else if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // normal response
{
if(0) {}
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications response
{
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
modbus_msg->DevId.Conformity = modbus_uart_buff[ind++];
modbus_msg->DevId.MoreFollows = modbus_uart_buff[ind++];
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
modbus_msg->DevId.NumbOfObj = modbus_uart_buff[ind++];
modbus_msg->ByteCnt = 0;
// Парсинг объектов идентификации устройства
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
int data_index = 0;
for(int obj = 0; obj < modbus_msg->DevId.NumbOfObj; obj++)
{
// Читаем ID объекта
uint8_t object_id = modbus_uart_buff[ind++];
tmp_data_addr[data_index++] = object_id;
// Читаем длину объекта
uint8_t object_length = modbus_uart_buff[ind++];
tmp_data_addr[data_index++] = object_length;
// Читаем данные объекта
for(int i = 0; i < object_length; i++)
{
tmp_data_addr[data_index++] = modbus_uart_buff[ind++];
}
modbus_msg->ByteCnt += (2 + object_length); // ID + длина + данные
}
}
#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#ifdef MODBUS_ENABLE_DIAGNOSTICS
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{
// Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8;
modbus_msg->MbData[0] |= modbus_uart_buff[ind++];
modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8;
modbus_msg->MbData[1] |= modbus_uart_buff[ind++];
}
#endif //MODBUS_ENABLE_DIAGNOSTICS
else // classic modbus response
{
// get byte count for read functions
if((modbus_msg->FuncCode == 0x01) || (modbus_msg->FuncCode == 0x02) ||
(modbus_msg->FuncCode == 0x03) || (modbus_msg->FuncCode == 0x04))
{
modbus_msg->ByteCnt = modbus_uart_buff[ind++];
// read data bytes
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++)
{
if(i % 2 == 0) // HI byte
tmp_data_addr[i/2] = (uint16_t)modbus_uart_buff[ind++] << 8;
else // LO byte
tmp_data_addr[i/2] |= modbus_uart_buff[ind++];
}
}
// for write functions - echo address and quantity
else if((modbus_msg->FuncCode == 0x05) || (modbus_msg->FuncCode == 0x06) ||
(modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10))
{
modbus_msg->Addr = modbus_uart_buff[ind++] << 8;
modbus_msg->Addr |= modbus_uart_buff[ind++];
modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
modbus_msg->Qnt |= modbus_uart_buff[ind++];
}
}
}
//---------------CRC----------------
//----------[last 2 bytes]----------
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
modbus_msg->MbCRC = modbus_uart_buff[ind++];
modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8;
if(modbus_msg->MbCRC != CRC_VALUE)
{
TrackerCnt_Err(hmodbus->rs_err);
return RS_PARSE_MSG_ERR;
}
return RS_OK;
}
/** @brief Сформировать запрос на чтение коилов */
RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg;
}
/** @brief Сформировать запрос на чтение дискретных регистров */
RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg;
}
/** @brief Сформировать запрос на чтение холдинг регистров */
RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg;
}
/** @brief Сформировать запрос на чтение инпут регистров */
RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg;
}
/** @brief Сформировать запрос на запись одного коила */
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value)
{
RS_MsgTypeDef msg = {slave_addr, FC_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0};
return msg;
}
/** @brief Сформировать запрос на запись одного регистра */
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value)
{
RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0};
return msg;
}
/** @brief Сформировать запрос на запись нескольких регистров */
RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data)
{
RS_MsgTypeDef msg = {slave_addr, FC_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0};
// Calculate byte count and prepare data
uint8_t byte_count = (quantity + 7) / 8;
msg.ByteCnt = byte_count;
// Copy coil data to message MbData array
for(int i = 0; i < byte_count; i++) {
if(i < MbData_size) {
msg.MbData[i] = coils_data[i];
}
}
return msg;
}
/** @brief Сформировать запрос на запись нескольких коилов */
RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data)
{
RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
msg.ByteCnt = quantity * 2; // Each register is 2 bytes
// Copy register data to message MbData array
for(int i = 0; i < quantity && i < MbData_size; i++) {
msg.MbData[i] = regs_data[i];
}
return msg;
}
//---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ-----------
RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_DIAGNOSTICS, {0}, 0, 0, 0, {sub_function, data}, 0, 0};
return msg;
}
RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0000, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RESTART_COMMUNICATIONS(uint8_t slave_addr, uint16_t data)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0001, data);
}
RS_MsgTypeDef MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0002, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_FORCE_LISTEN_ONLY_MODE(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0004, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000A, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000B, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000C, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000D, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000E, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000F, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NAK_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0010, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0011, 0x0000);
}
RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr)
{
return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0012, 0x0000);
}
//---------ИДЕНТИФИКАТОРЫ МОДБАС-----------
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg;
}
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg;
}
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg;
}
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id)
{
RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg;
}
#endif //MODBUS_ENABLE_MASTER