Бета добавление новых кодов исключения Улучшение механики ответа с задержкой, когда время ответа определяется пользователем, а не в прерывании сразу
534 lines
19 KiB
C
534 lines
19 KiB
C
/**
|
|
*******************************************************************************
|
|
* @file modbus_slave.c
|
|
* @brief Модуль для реализации слейв MODBUS.
|
|
*******************************************************************************
|
|
* @details
|
|
Файл содержит реализацию функций для работы Modbus в режиме слейва.
|
|
|
|
@section slave Функции и макросы
|
|
- MB_Slave_ResponseLater() — Выставить флаг на ответ вне прерывания
|
|
- MB_Slave_SendResponse() — Ответить на запрос
|
|
|
|
- MB_Slave_Response() — Ответ на запрос
|
|
- MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва.
|
|
- MB_Slave_Parse_Message() — Парс сообщения в режиме слейва.
|
|
******************************************************************************/
|
|
#include "modbus.h"
|
|
|
|
#ifdef MODBUS_ENABLE_SLAVE
|
|
|
|
/**
|
|
* @brief Ответить позже, не в прерывании.
|
|
* @param hmodbus Указатель на хендлер RS.
|
|
* @param ResponseCode Код запроса на который надо ответить.
|
|
* @return HAL Status.
|
|
* @details Отменяет ответ в прерывании на запрос.
|
|
Используется вместе с @ref MB_Slave_SendResponse
|
|
*/
|
|
HAL_StatusTypeDef MB_Slave_ResponseLater(RS_HandleTypeDef *hmodbus, uint8_t ResponseCode)
|
|
{
|
|
hmodbus->f.DeferredResponse = ResponseCode;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Ответить на запрос.
|
|
* @param hmodbus Указатель на хендлер RS.
|
|
* @param ResponseCode Код запроса на который надо ответить.
|
|
* @param error Тип ошибки или её отсутствия в ответе.
|
|
* @return HAL Status.
|
|
* @details Ответить на запрос вне прерывания.
|
|
Используется вместе с @ref MB_Slave_ResponseLater
|
|
*/
|
|
HAL_StatusTypeDef MB_Slave_SendResponse(RS_HandleTypeDef *hmodbus, uint8_t ResponseCode, MB_ExceptionTypeDef error)
|
|
{
|
|
RS_StatusTypeDef MB_RES = 0;
|
|
if(hmodbus->f.DeferredResponse == ResponseCode)
|
|
{
|
|
hmodbus->f.DeferredResponse = 0;
|
|
switch(error)
|
|
{
|
|
case ET_NO_ERRORS:
|
|
break;
|
|
|
|
case ET_ACKNOWLEDGE:
|
|
MB_Diagnostics_SlaveNAKCnt();
|
|
break;
|
|
case ET_SLAVE_DEVICE_BUSY:
|
|
MB_Diagnostics_SlaveBusyCnt();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(error != ET_NO_ERRORS)
|
|
{
|
|
MB_Diagnostics_ExceptionErrorCnt();
|
|
TrackerCnt_Warn(hmodbus->rs_err);
|
|
hmodbus->pMessagePtr->FuncCode |= FC_ERR_VALUES_START;
|
|
hmodbus->pMessagePtr->Except_Code = error;
|
|
}
|
|
|
|
hmodbus->RS_STATUS = RS_Handle_Transmit_Start(hmodbus, hmodbus->pMessagePtr);
|
|
}
|
|
return HAL_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Ответ на сообщение в режиме слейва.
|
|
* @param hmodbus Указатель на хендлер RS.
|
|
* @param modbus_msg Указатель на структуру сообщения.
|
|
* @return RS_RES Статус о результате ответа на комманду.
|
|
*/
|
|
RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
|
{
|
|
RS_StatusTypeDef MB_RES = 0;
|
|
hmodbus->f.MessageHandled = 0;
|
|
hmodbus->f.EchoResponse = 0;
|
|
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
|
|
|
|
MB_Diagnostics_BusMessageCnt();
|
|
if(hmodbus->ID == 0 || modbus_msg->DeviceAddr == 0)
|
|
{
|
|
MB_Diagnostics_SlaveNoResponseCnt(); // <-- Устройство не отвечает на широковещательные сообщения
|
|
hmodbus->RS_STATUS = RS_SKIP;
|
|
return RS_Handle_Receive_Start(hmodbus, modbus_msg);
|
|
}
|
|
MB_Diagnostics_SlaveMessageCnt();
|
|
|
|
if(modbus_msg->FuncCode < FC_ERR_VALUES_START)// if no errors after parsing
|
|
{
|
|
switch (modbus_msg->FuncCode)
|
|
{
|
|
// Read Coils
|
|
case FC_R_COILS:
|
|
hmodbus->f.MessageHandled = MB_Process_Read_Coils(hmodbus->pMessagePtr);
|
|
break;
|
|
|
|
// Read Hodling Registers
|
|
case FC_R_HOLD_REGS:
|
|
hmodbus->f.MessageHandled = MB_Process_Read_Hold_Regs(hmodbus->pMessagePtr);
|
|
#ifdef MODBUS_ENABLE_OSCIL
|
|
int is_oscil_data_register = ((hmodbus->pMessagePtr->Addr >= R_HOLDING_OSCIL_ADDR+4) && (hmodbus->pMessagePtr->Addr + hmodbus->pMessagePtr->Qnt <= (R_HOLDING_OSCIL_ADDR+5+(sizeof(MB_OscilTypeDef)/2))));
|
|
if(is_oscil_data_register)
|
|
MB_Oscil_UpdateTail(&MB_INTERNAL.oscil);
|
|
#endif
|
|
break;
|
|
case FC_R_IN_REGS:
|
|
hmodbus->f.MessageHandled = MB_Process_Read_Input_Regs(hmodbus->pMessagePtr);
|
|
break;
|
|
|
|
|
|
// Write Single Coils
|
|
case FC_W_COIL:
|
|
hmodbus->f.MessageHandled = MB_Process_Write_Single_Coil(hmodbus->pMessagePtr);
|
|
if(hmodbus->f.MessageHandled)
|
|
{
|
|
hmodbus->f.DataUpdated = 1;
|
|
hmodbus->f.EchoResponse = 1;
|
|
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
|
}
|
|
break;
|
|
|
|
case FC_W_HOLD_REG:
|
|
hmodbus->f.MessageHandled = MB_Process_Write_Single_Reg(hmodbus->pMessagePtr);
|
|
if(hmodbus->f.MessageHandled)
|
|
{
|
|
hmodbus->f.DataUpdated = 1;
|
|
hmodbus->f.EchoResponse = 1;
|
|
hmodbus->RS_Message_Size -= 2; // echo response if write ok (minus 2 cause of two CRC bytes)
|
|
}
|
|
break;
|
|
|
|
// Write Multiple Coils
|
|
case FC_W_COILS:
|
|
hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Coils(hmodbus->pMessagePtr);
|
|
if(hmodbus->f.MessageHandled)
|
|
{
|
|
hmodbus->f.DataUpdated = 1;
|
|
hmodbus->f.EchoResponse = 1;
|
|
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
|
}
|
|
break;
|
|
|
|
// Write Multiple Registers
|
|
case FC_W_HOLD_REGS:
|
|
hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Regs(hmodbus->pMessagePtr);
|
|
if(hmodbus->f.MessageHandled)
|
|
{
|
|
hmodbus->f.DataUpdated = 1;
|
|
hmodbus->f.EchoResponse = 1;
|
|
hmodbus->RS_Message_Size = 6; // echo response if write ok (withous data bytes)
|
|
}
|
|
break;
|
|
|
|
case FC_R_DEVICE_ID:
|
|
hmodbus->f.MessageHandled = MB_Process_Read_Device_Identifications(hmodbus->pMessagePtr);
|
|
break;
|
|
|
|
// Добавить в switch-case после других case:
|
|
case FC_R_DIAGNOSTICS:
|
|
hmodbus->f.MessageHandled = MB_Process_Diagnostics(hmodbus->pMessagePtr);
|
|
break;
|
|
|
|
/* unknown func code */
|
|
default:
|
|
modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
|
|
}
|
|
|
|
// Проверяем режим устройства - если Listen Only, не обрабатываем команды
|
|
if (MB_GetDeviceMode() == MODBUS_LISTEN_ONLY_MODE)
|
|
{
|
|
MB_Diagnostics_SlaveNoResponseCnt();
|
|
hmodbus->RS_STATUS = RS_SKIP;
|
|
return RS_Handle_Receive_Start(hmodbus, modbus_msg);;
|
|
}
|
|
|
|
// Проверяем статус обработки запроса
|
|
if(hmodbus->f.MessageHandled == 0)
|
|
{
|
|
MB_Diagnostics_ExceptionErrorCnt();
|
|
TrackerCnt_Warn(hmodbus->rs_err);
|
|
modbus_msg->FuncCode |= FC_ERR_VALUES_START;
|
|
}
|
|
else
|
|
{
|
|
TrackerCnt_Ok(hmodbus->rs_err);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// if we need response - check that transmit isnt busy
|
|
if( RS_Is_TX_Busy(hmodbus) )
|
|
RS_Abort(hmodbus, ABORT_TX); // if tx busy - set it free
|
|
|
|
// Transmit right there, or sets (fDeferredResponse) to transmit response in main code
|
|
if(hmodbus->f.DeferredResponse == 0)
|
|
{
|
|
MB_RES = RS_Handle_Transmit_Start(hmodbus, modbus_msg);
|
|
}
|
|
else
|
|
{
|
|
// RS_Handle_Receive_Start(hmodbus, modbus_msg);
|
|
// hmodbus->f.DeferredResponse = 0;
|
|
}
|
|
|
|
hmodbus->RS_STATUS = MB_RES;
|
|
return MB_RES;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief Сбор сообщения в буфер UART в режиме слейв (фрейм слейва из msg -> uart).
|
|
* @param hmodbus Указатель на хендлер RS.
|
|
* @param modbus_msg Указатель на структуру сообщения.
|
|
* @param modbus_uart_buff Указатель на буффер UART.
|
|
* @return RS_RES Статус о результате заполнения буфера.
|
|
*/
|
|
RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
|
|
{
|
|
int ind = 0; // ind for modbus-uart buffer
|
|
|
|
if(hmodbus->f.EchoResponse && (modbus_msg->Except_Code == ET_NO_ERRORS)) // if echo response need
|
|
ind = hmodbus->RS_Message_Size;
|
|
else
|
|
{
|
|
//------INFO ABOUT DATA/MESSAGE------
|
|
#ifdef MODBUS_PROTOCOL_TCP
|
|
modbus_uart_buff[ind++] = modbus_msg->TransactionID >> 8;
|
|
modbus_uart_buff[ind++] = modbus_msg->TransactionID& 0xFF;
|
|
|
|
modbus_uart_buff[ind++] = modbus_msg->ProtocolID >> 8;
|
|
modbus_uart_buff[ind++] = modbus_msg->ProtocolID& 0xFF;
|
|
|
|
modbus_uart_buff[ind++] = modbus_msg->PDULength >> 8;
|
|
modbus_uart_buff[ind++] = modbus_msg->PDULength& 0xFF;
|
|
#endif
|
|
//-----------[first bytes]-----------
|
|
// set ID of message/user
|
|
modbus_uart_buff[ind++] = modbus_msg->DeviceAddr;
|
|
|
|
// set dat or err response
|
|
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) // devide identifications header
|
|
{
|
|
modbus_uart_buff[ind++] = 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;
|
|
|
|
if (modbus_msg->ByteCnt > MbData_size*2) // if ByteCnt less than MbData_size
|
|
{
|
|
TrackerCnt_Err(hmodbus->rs_err);
|
|
return RS_COLLECT_MSG_ERR;
|
|
}
|
|
|
|
|
|
//---------------DATA----------------
|
|
//-----------[data bytes]------------
|
|
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
|
|
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
|
|
{ // set data
|
|
modbus_uart_buff[ind++] = *tmp_data_addr;
|
|
tmp_data_addr++;
|
|
}
|
|
|
|
}
|
|
#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
|
|
#ifdef MODBUS_ENABLE_DIAGNOSTICS
|
|
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
|
|
{
|
|
// Diagnostics special format: [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 // modbus data header
|
|
{
|
|
// set size of received data
|
|
if (modbus_msg->ByteCnt <= MbData_size*2) // if ByteCnt less than MbData_size
|
|
modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
|
|
else // otherwise return data_size err
|
|
{
|
|
TrackerCnt_Err(hmodbus->rs_err);
|
|
return RS_COLLECT_MSG_ERR;
|
|
}
|
|
|
|
//---------------DATA----------------
|
|
//-----------[data bytes]------------
|
|
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
|
|
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
|
|
{ // set data
|
|
if (i%2 == 0) // HI byte
|
|
modbus_uart_buff[ind++] = (*tmp_data_addr)>>8;
|
|
else // LO byte
|
|
{
|
|
modbus_uart_buff[ind++] = *tmp_data_addr;
|
|
tmp_data_addr++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
else // if some error occur
|
|
{ // send expection code
|
|
modbus_uart_buff[ind++] = modbus_msg->Except_Code;
|
|
}
|
|
}
|
|
if(ind < 0)
|
|
return RS_COLLECT_MSG_ERR;
|
|
|
|
//---------------CRC----------------
|
|
//---------[last 16 bytes]----------
|
|
#ifndef MODBUS_PROTOCOL_TCP
|
|
// calc crc of received data
|
|
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
|
|
// write crc to message structure and modbus-uart buffer
|
|
modbus_msg->MbCRC = CRC_VALUE;
|
|
modbus_uart_buff[ind++] = CRC_VALUE;
|
|
modbus_uart_buff[ind++] = CRC_VALUE >> 8;
|
|
#endif
|
|
|
|
hmodbus->RS_Message_Size = ind;
|
|
|
|
return RS_OK; // returns ok
|
|
}
|
|
|
|
/**
|
|
* @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;
|
|
|
|
if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
|
|
{
|
|
mb_func_size = 1;
|
|
}
|
|
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID)
|
|
{
|
|
mb_func_size = 0;
|
|
}
|
|
else if ((modbus_msg->FuncCode & ~FC_ERR_VALUES_START) < 0x0F)
|
|
{
|
|
mb_func_size = 1;
|
|
}
|
|
else
|
|
{
|
|
mb_func_size = modbus_msg->ByteCnt + 2;
|
|
}
|
|
|
|
|
|
mb_func_size = RS_RX_FIRST_PART_SIZE + mb_func_size; // size of whole message
|
|
return mb_func_size;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Парс сообщения в режиме слейв (фрейм мастера из uart -> msg).
|
|
* @param hmodbus Указатель на хендлер RS.
|
|
* @param modbus_msg Указатель на структуру сообщения.
|
|
* @param modbus_uart_buff Указатель на буффер UART.
|
|
* @return RS_RES Статус о результате заполнения структуры.
|
|
* @details Заполнение структуры сообщения из буффера UART.
|
|
*/
|
|
RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
|
|
{
|
|
uint32_t check_empty_buff;
|
|
int ind = 0; // ind for modbus-uart buffer
|
|
hmodbus->f.RX_Continue = 0;
|
|
int expected_size = 0;
|
|
//-----INFO ABOUT DATA/MESSAGE-------
|
|
#ifdef MODBUS_PROTOCOL_TCP
|
|
modbus_msg->TransactionID =modbus_uart_buff[ind++]<<8;
|
|
modbus_msg->TransactionID |=modbus_uart_buff[ind++];
|
|
|
|
modbus_msg->ProtocolID =modbus_uart_buff[ind++]<<8;
|
|
modbus_msg->ProtocolID |=modbus_uart_buff[ind++];
|
|
|
|
modbus_msg->PDULength =modbus_uart_buff[ind++]<<8;
|
|
modbus_msg->PDULength |=modbus_uart_buff[ind++];
|
|
#endif
|
|
//-----------[first bits]------------
|
|
// get ID of message/user
|
|
if(modbus_uart_buff[ind] != hmodbus->ID)
|
|
{
|
|
modbus_msg->DeviceAddr = 0;
|
|
ind++;
|
|
}
|
|
else
|
|
{
|
|
modbus_msg->DeviceAddr = modbus_uart_buff[ind++];
|
|
}
|
|
|
|
// get func code
|
|
modbus_msg->FuncCode = modbus_uart_buff[ind++];
|
|
if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // явная херня
|
|
{
|
|
MB_Diagnostics_SlaveNAKCnt();
|
|
modbus_msg->DeviceAddr = 0;
|
|
return RS_SKIP;
|
|
}
|
|
|
|
if(0) {}
|
|
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
|
|
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // if it device identifications request
|
|
{
|
|
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
|
|
modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
|
|
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
|
|
modbus_msg->ByteCnt = 0;
|
|
}
|
|
#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
|
|
#ifdef MODBUS_ENABLE_DIAGNOSTICS
|
|
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
|
|
{
|
|
// Diagnostics: читаем 4 байта в MbData[0] и MbData[1]
|
|
// Sub-function
|
|
modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8;
|
|
modbus_msg->MbData[0] |= modbus_uart_buff[ind++];
|
|
// Data
|
|
modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8;
|
|
modbus_msg->MbData[1] |= modbus_uart_buff[ind++];
|
|
modbus_msg->Addr = 0; // не использует Addr
|
|
modbus_msg->Qnt = 0; // не использует Qnt
|
|
}
|
|
#endif //MODBUS_ENABLE_DIAGNOSTICS
|
|
else // if its classic modbus request
|
|
{
|
|
// get address from CMD
|
|
modbus_msg->Addr = modbus_uart_buff[ind++] << 8;
|
|
modbus_msg->Addr |= modbus_uart_buff[ind++];
|
|
|
|
// get address from CMD
|
|
modbus_msg->Qnt = modbus_uart_buff[ind++] << 8;
|
|
modbus_msg->Qnt |= modbus_uart_buff[ind++];
|
|
}
|
|
|
|
if((hmodbus->pMessagePtr->FuncCode == 0x0F) || (hmodbus->pMessagePtr->FuncCode == 0x10))
|
|
hmodbus->pMessagePtr->ByteCnt = modbus_uart_buff[ind++];
|
|
else
|
|
hmodbus->pMessagePtr->ByteCnt = 0;
|
|
|
|
expected_size = MB_Define_Size_of_Function(hmodbus, modbus_msg);
|
|
// если размер меньше ожидаемого - продолжаем принимать
|
|
if(hmodbus->RS_Message_Size < expected_size)
|
|
{
|
|
hmodbus->f.RX_Continue = 1;
|
|
return RS_SKIP;
|
|
}
|
|
// если больше Ошибка
|
|
else if (hmodbus->RS_Message_Size > expected_size)
|
|
{
|
|
MB_Diagnostics_CommunicationErrorCnt();
|
|
return RS_PARSE_MSG_ERR;
|
|
}
|
|
|
|
//---------------DATA----------------
|
|
// (optional)
|
|
if (modbus_msg->ByteCnt != 0)
|
|
{
|
|
//check that data size is correct
|
|
if (modbus_msg->ByteCnt > MbData_size*2)
|
|
{
|
|
TrackerCnt_Err(hmodbus->rs_err);
|
|
modbus_msg->FuncCode |= FC_ERR_VALUES_START;
|
|
MB_Diagnostics_CommunicationErrorCnt();
|
|
return RS_PARSE_MSG_ERR;
|
|
}
|
|
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
|
|
for(int i = 0; i < modbus_msg->ByteCnt; i++)
|
|
{ // set data
|
|
if (i%2 == 0)
|
|
*tmp_data_addr = ((uint16_t)modbus_uart_buff[ind++] << 8);
|
|
else
|
|
{
|
|
*tmp_data_addr |= modbus_uart_buff[ind++];
|
|
tmp_data_addr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------CRC----------------
|
|
//----------[last 16 bits]----------
|
|
#ifndef MODBUS_PROTOCOL_TCP
|
|
// calc crc of received data
|
|
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
|
|
// get crc of received data
|
|
modbus_msg->MbCRC = modbus_uart_buff[ind++];
|
|
modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8;
|
|
// compare crc
|
|
if (modbus_msg->MbCRC != CRC_VALUE)
|
|
{
|
|
MB_Diagnostics_CommunicationErrorCnt();
|
|
TrackerCnt_Err(hmodbus->rs_err);
|
|
modbus_msg->FuncCode |= FC_ERR_VALUES_START;
|
|
}
|
|
#endif
|
|
|
|
return RS_OK;
|
|
}
|
|
|
|
#endif //MODBUS_ENABLE_SLAVE
|