/** ******************************************************************************* * @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; iQnt; 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; iQnt; i++) { *(pHoldRegs++) = modbus_msg->MbData[i]; } return 1; } #endif //MODBUS_ENABLE_HOLDINGS