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

162 lines
6.6 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_holdregs.c
* @brief Реализация работы с регистрами хранения Modbus
*******************************************************************************
* @details
Модуль для доступа к регистрам внутри программы:
- Функции для доступа к регистрам хранения по глобальным адресам
Модуль обработки команд для holding registers (регистров хранения):
- Чтение множественных регистров (0x03) - копирование данных в буфер ответа
- Запись одиночного регистра (0x06) - прямая запись значения
- Запись множественных регистров (0x10) - пакетная запись из буфера
@section hvalid Валидация данных:
- Проверка соответствия количества байт и регистров
- Валидация адресов через MB_DefineRegistersAddress()
- Обработка исключений при некорректных запросах
******************************************************************************/
#include "modbus_inputregs.h"
#ifdef MODBUS_ENABLE_HOLDINGS
/**
* @brief Записать регистр хранения по глобальному адресу.
* @param Addr Адрес регистра.
* @param WriteVal Число для записи.
* @return ExceptionCode Код исключения если регистра по адресу не существует, и ET_NO_ERRORS если все ок.
*
* @details Позволяет обратиться к любому регистру по его глобальному адрессу.
Вне зависимости от того как регистры размещены в памяти.
*/
MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal)
{
//---------CHECK FOR ERRORS----------
MB_ExceptionTypeDef Exception = ET_NO_ERRORS;
uint16_t *pHoldRegs;
//------------WRITE COIL-------------
Exception = MB_DefineRegistersAddress(&pHoldRegs, Addr, 1, RegisterType_Holding, 1);
if(Exception == ET_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, 0);
if(Exception) // if exception is not given to func fill it
*Exception = Exception_tmp;
if(Exception_tmp == ET_NO_ERRORS)
{
return *(pHoldRegs);
}
else
{
return 0;
}
}
/**
* @brief Обработать функцию Read Holding Registers (03 - 0x03).
* @param modbus_msg Указатель на структуру собщения modbus.
* @return fMessageHandled Статус о результате обработки комманды.
* @details Обработка команды Read Holding Registers.
*/
uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
// get origin address for data
uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding, 0); // определение адреса регистров
if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0;
//-----------READING REGS------------
// setup output message data size
modbus_msg->ByteCnt = modbus_msg->Qnt*2; // *2 because we transmit 8 bits, not 16 bits
// read data
int i;
for (i = 0; i<modbus_msg->Qnt; i++)
{
modbus_msg->MbData[i] = *(pHoldRegs++);
}
return 1;
}
/**
* @brief Обработать функцию Write Single Register (06 - 0x06).
* @param modbus_msg Указатель на структуру собщения modbus.
* @return fMessageHandled Статус о результате обработки комманды.
* @details Обработка команды Write Single Register.
*/
uint8_t MB_Process_Write_Single_Reg(RS_MsgTypeDef *modbus_msg)
{
// get origin address for data
uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding, 1); // определение адреса регистров
if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0;
//-----------WRITTING REG------------
*(pHoldRegs) = modbus_msg->Qnt;
return 1;
}
/**
* @brief Обработать функцию Write Multiple Registers (16 - 0x10).
* @param modbus_msg Указатель на структуру собщения modbus.
* @return fMessageHandled Статус о результате обработки комманды.
* @details Обработка команды Write Multiple Registers.
*/
uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
{
//---------CHECK FOR ERRORS----------
if (modbus_msg->Qnt*2 != modbus_msg->ByteCnt)
{ // if quantity and bytes count arent match
modbus_msg->Except_Code = 3;
return 0;
}
// get origin address for data
uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding, 1); // определение адреса регистров
if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0;
//-----------WRITTING REGS-----------
for (int i = 0; i<modbus_msg->Qnt; i++)
{
*(pHoldRegs++) = modbus_msg->MbData[i];
}
return 1;
}
#endif //MODBUS_ENABLE_HOLDINGS