release 0.3.2 Фиксы:
- Data Access API расширено функциями для чтения/записи регистров - API для реквестов MB_RespGet.. перенесено в modbus_master - Мастер: коллбек реквеста вызывается и при таймауте - В коллбеке можно понять статус реквеста по hmodbus->RS_STATUS
This commit is contained in:
@@ -57,7 +57,7 @@ MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteV
|
||||
/**
|
||||
* @brief Считать коил по глобальному адресу.
|
||||
* @param Addr Адрес коила.
|
||||
* @param Exception Указатель на переменную для кода исключения, в случа неудачи при чтении.
|
||||
* @param Exception Указатель на переменную для кода исключения, в случае неудачи при чтении.
|
||||
* @return uint16_t Возвращает весь регистр с маской на запрошенном коиле.
|
||||
*
|
||||
* @details Позволяет обратиться к любому коилу по его глобальному адрессу.
|
||||
@@ -86,51 +86,6 @@ uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @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->Func_Code != MB_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->DATA[data_index] >> (bit_index+8)) & 0x01;
|
||||
else
|
||||
*coil_state = (modbus_msg->DATA[data_index] >> bit_index) & 0x01;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработать функцию Read Coils (01 - 0x01).
|
||||
* @param modbus_msg Указатель на структуру собщения modbus.
|
||||
@@ -284,7 +239,6 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
|
||||
#else //MODBUS_ENABLE_COILS
|
||||
|
||||
|
||||
int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) {return 0;}
|
||||
MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) {return ILLEGAL_FUNCTION;}
|
||||
uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;}
|
||||
uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file modbus_core.c
|
||||
* @brief Базовая реализация ядра Modbus (заглушка)
|
||||
* @brief Базовая реализация ядра Modbus
|
||||
******************************************************************************
|
||||
* @details
|
||||
В текущей реализации этот файл служит заглушкой для будущего расширения
|
||||
|
||||
@@ -21,132 +21,6 @@
|
||||
MB_DeviceIdentificationsTypeDef MB_DEVID; ///< Глобальная структура идентификаторов устройства
|
||||
|
||||
|
||||
/**
|
||||
* @brief Получить количество объектов в сообщении
|
||||
* @param modbus_msg Указатель на структуру сообщения
|
||||
* @return int Количество объектов
|
||||
*/
|
||||
int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
if(modbus_msg == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Проверяем что ответ связан с диагностикой
|
||||
if(modbus_msg->Func_Code != MB_R_DEVICE_INFO)
|
||||
{
|
||||
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->Func_Code != MB_R_DEVICE_INFO)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *data = (uint8_t*)modbus_msg->DATA;
|
||||
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->Func_Code != MB_R_DEVICE_INFO)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(index >= modbus_msg->DevId.NumbOfObj)
|
||||
return 0;
|
||||
|
||||
uint8_t *data = (uint8_t*)modbus_msg->DATA;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -674,9 +548,7 @@ void MB_DeviceInentificationInit(void)
|
||||
#else //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
|
||||
|
||||
/* Получить количество объектов в сообщении */
|
||||
int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) {return 0;}
|
||||
int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) {return 0;}
|
||||
|
||||
void MB_WriteSingleObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj) {}
|
||||
void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) {}
|
||||
uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
|
||||
@@ -36,29 +36,6 @@ void MB_DiagnosticsInit(void)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Получить данные диагностики из сообщения (DATA[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->Func_Code != MB_R_DIAGNOSTIC)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
*data = modbus_msg->DATA[1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Выставить бит в регистре диагностике
|
||||
* @param bit_num Номер бита для выставления (1-15, 0 бит нельзя выставить)
|
||||
@@ -319,7 +296,6 @@ MB_DeviceModeTypeDef MB_GetDeviceMode(void)
|
||||
#else //MODBUS_ENABLE_DIAGNOSTICS
|
||||
|
||||
void MB_DiagnosticsInit(void) {}
|
||||
int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) {return 0;}
|
||||
int MB_Diagnostics_WriteBit(int bit_num, int bit_state) {return 0;}
|
||||
int MB_Diagnostics_GetBit(int bit_num) {return 0;}
|
||||
uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
|
||||
@@ -24,6 +24,66 @@
|
||||
#ifdef MODBUS_ENABLE_HOLDINGS
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Записать регистр хранения по глобальному адресу.
|
||||
* @param Addr Адрес регистра.
|
||||
* @param WriteVal Число для записи.
|
||||
* @return ExceptionCode Код исключения если регистра по адресу не существует, и NO_ERRORS если все ок.
|
||||
*
|
||||
* @details Позволяет обратиться к любому регистру по его глобальному адрессу.
|
||||
Вне зависимости от того как регистры размещены в памяти.
|
||||
*/
|
||||
MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
MB_ExceptionTypeDef Exception = NO_ERRORS;
|
||||
uint16_t *pHoldRegs;
|
||||
|
||||
//------------WRITE COIL-------------
|
||||
Exception = MB_DefineRegistersAddress(&pHoldRegs, Addr, 1, RegisterType_Holding);
|
||||
if(Exception == NO_ERRORS)
|
||||
{
|
||||
*(pHoldRegs) = WriteVal;
|
||||
}
|
||||
return Exception;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Считать регистр хранения по глобальному адресу.
|
||||
* @param Addr Адрес регистра.
|
||||
* @param Exception Указатель на переменную для кода исключения, в случае неудачи при чтении.
|
||||
* @return uint16_t Возвращает значение регистра.
|
||||
*
|
||||
* @details Позволяет обратиться к любому регистру по его глобальному адрессу.
|
||||
Вне зависимости от того как регистры размещены в памяти.
|
||||
*/
|
||||
uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
MB_ExceptionTypeDef Exception_tmp = 0;
|
||||
|
||||
uint16_t *pHoldRegs;
|
||||
|
||||
//------------READ COIL--------------
|
||||
Exception_tmp = MB_DefineRegistersAddress(&pHoldRegs, Addr, 1, RegisterType_Holding);
|
||||
|
||||
if(Exception) // if exception is not given to func fill it
|
||||
*Exception = Exception_tmp;
|
||||
|
||||
if(Exception_tmp == NO_ERRORS)
|
||||
{
|
||||
return *(pHoldRegs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Обработать функцию Read Holding Registers (03 - 0x03).
|
||||
* @param modbus_msg Указатель на структуру собщения modbus.
|
||||
@@ -34,7 +94,7 @@ uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
// get origin address for data
|
||||
uint16_t *pHoldRegs;
|
||||
uint16_t *pHoldRegs;
|
||||
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
|
||||
if(modbus_msg->Except_Code != NO_ERRORS)
|
||||
return 0;
|
||||
@@ -102,6 +162,8 @@ uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
|
||||
|
||||
#else //MODBUS_ENABLE_HOLDINGS
|
||||
|
||||
MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal) {return ILLEGAL_FUNCTION;}
|
||||
uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;}
|
||||
uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
uint8_t MB_Process_Write_Single_Reg(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
|
||||
@@ -14,6 +14,65 @@
|
||||
|
||||
#ifdef MODBUS_ENABLE_INPUTS
|
||||
|
||||
|
||||
/**
|
||||
* @brief Записать входной регистр по глобальному адресу.
|
||||
* @param Addr Адрес регистра.
|
||||
* @param WriteVal Число для записи.
|
||||
* @return ExceptionCode Код исключения если регистра по адресу не существует, и NO_ERRORS если все ок.
|
||||
*
|
||||
* @details Позволяет обратиться к любому регистру по его глобальному адрессу.
|
||||
Вне зависимости от того как регистры размещены в памяти.
|
||||
*/
|
||||
MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
MB_ExceptionTypeDef Exception = NO_ERRORS;
|
||||
uint16_t *pInRegs;
|
||||
|
||||
//------------WRITE COIL-------------
|
||||
Exception = MB_DefineRegistersAddress(&pInRegs, Addr, 1, RegisterType_Input);
|
||||
if(Exception == NO_ERRORS)
|
||||
{
|
||||
*(pInRegs) = WriteVal;
|
||||
}
|
||||
return Exception;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Считать входной регистр по глобальному адресу.
|
||||
* @param Addr Адрес регистра.
|
||||
* @param Exception Указатель на переменную для кода исключения, в случае неудачи при чтении.
|
||||
* @return uint16_t Возвращает значение регистра.
|
||||
*
|
||||
* @details Позволяет обратиться к любому регистру по его глобальному адрессу.
|
||||
Вне зависимости от того как регистры размещены в памяти.
|
||||
*/
|
||||
uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
|
||||
{
|
||||
//---------CHECK FOR ERRORS----------
|
||||
MB_ExceptionTypeDef Exception_tmp = 0;
|
||||
|
||||
uint16_t *pInRegs;
|
||||
|
||||
//------------READ COIL--------------
|
||||
Exception_tmp = MB_DefineRegistersAddress(&pInRegs, Addr, 1, RegisterType_Input);
|
||||
|
||||
if(Exception) // if exception is not given to func fill it
|
||||
*Exception = Exception_tmp;
|
||||
|
||||
if(Exception_tmp == NO_ERRORS)
|
||||
{
|
||||
return *(pInRegs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Обработать функцию Read Input Registers (04 - 0x04).
|
||||
* @param modbus_msg Указатель на структуру собщения modbus.
|
||||
@@ -47,6 +106,8 @@ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
|
||||
|
||||
#else //MODBUS_ENABLE_INPUTS
|
||||
|
||||
MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal) {return ILLEGAL_FUNCTION;}
|
||||
uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;}
|
||||
uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
|
||||
#endif
|
||||
@@ -53,6 +53,203 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1
|
||||
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->Func_Code != MB_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->DATA[data_index] >> (bit_index+8)) & 0x01;
|
||||
else
|
||||
*coil_state = (modbus_msg->DATA[data_index] >> bit_index) & 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->Func_Code != MB_R_DEVICE_INFO)
|
||||
{
|
||||
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->Func_Code != MB_R_DEVICE_INFO)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *data = (uint8_t*)modbus_msg->DATA;
|
||||
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->Func_Code != MB_R_DEVICE_INFO)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(index >= modbus_msg->DevId.NumbOfObj)
|
||||
return 0;
|
||||
|
||||
uint8_t *data = (uint8_t*)modbus_msg->DATA;
|
||||
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 Получить данные диагностики из сообщения (DATA[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->Func_Code != MB_R_DIAGNOSTIC)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
*data = modbus_msg->DATA[1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Определить размер модбас запроса (МАСТЕР версия).
|
||||
* @param hRS Указатель на хендлер RS.
|
||||
@@ -487,6 +684,11 @@ RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t obj
|
||||
RS_MsgTypeDef msg_dummy = {0};
|
||||
|
||||
int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) {return 0;}
|
||||
int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) {return 0;}
|
||||
int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg) {return 0;}
|
||||
int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) {return 0;}
|
||||
int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) {return 0;}
|
||||
int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) {return 0;}
|
||||
|
||||
RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;}
|
||||
RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;}
|
||||
|
||||
@@ -348,16 +348,18 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
||||
RS_Set_RX_End(hRS);
|
||||
|
||||
// Парсим наше сообщение
|
||||
RS_StatusTypeDef parse_res = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr);
|
||||
hRS->RS_STATUS = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr);
|
||||
|
||||
// Если сообещине принято корректно
|
||||
if(parse_res == RS_OK)
|
||||
if(hRS->RS_STATUS == RS_OK)
|
||||
{
|
||||
RS_Timeout_Stop(hRS);
|
||||
|
||||
hRS->lastPacketTick = uwTick;
|
||||
hRS->lastPacketTick = local_time();
|
||||
if(hRS->sRS_Mode < RS_MASTER_MODE_START)
|
||||
{
|
||||
RS_Response(hRS, hRS->pMessagePtr); // отвечаем на запрос
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hRS->pCallback)
|
||||
@@ -435,12 +437,20 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS)
|
||||
HAL_TIM_IRQHandler(hRS->htim);
|
||||
|
||||
RS_Abort(hRS, ABORT_RS);
|
||||
|
||||
|
||||
if(hRS->pMessagePtr->MbAddr == hRS->ID) // ошибка если таймаут по нашему сообщению
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
hRS->RS_STATUS = RS_TIMEOUT;
|
||||
|
||||
if(hRS->sRS_Mode < RS_MASTER_MODE_START)
|
||||
if(hRS->pMessagePtr->MbAddr == hRS->ID) // ошибка если таймаут по нашему сообщению
|
||||
TrackerCnt_Err(hRS->rs_err);
|
||||
|
||||
if(hRS->sRS_Mode == RS_MASTER_REQUEST) {
|
||||
// Мастер: таймаут ответа -> освобождаем для нового запроса
|
||||
if(hRS->sRS_Mode >= RS_MASTER_MODE_START)
|
||||
{ // Мастер: коллбек и освобождение для нового запроса
|
||||
if(hRS->pCallback)
|
||||
{
|
||||
hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ
|
||||
}
|
||||
RS_Set_Free(hRS);
|
||||
} else {
|
||||
// Слейв: перезапускаем прием
|
||||
|
||||
Reference in New Issue
Block a user