/** ****************************************************************************** * @file modbus_coils.h * @brief Работа с коилами Modbus ****************************************************************************** @addtogroup MODBUS_COILS Coils Tools @ingroup MODBUS_INTERNAL ****************************************************************************** * @details Модуль предоставляет функции и макросы для работы с битовыми данными: - Чтение coils (0x01) Упаковка битов в байты - Запись одиночного coil (0x05) Установка/сброс бита - Запись множественных coils (0x0F) - распаковка байтов в биты - Макросы для локального доступа к coils @section Организация битовых данных: Coils упакованы в 16-битные слова для эффективного использования памяти. Биты нумеруются от младшего к старшему внутри каждого слова. @section Адресация: - Глобальная - абсолютный адрес в пространстве Modbus - Локальная - относительный адрес внутри массива coils - Макросы автоматически вычисляют смещения и маски ******************************************************************************/ #ifndef __MODBUS_COILS_H_ #define __MODBUS_COILS_H_ #include "modbus_core.h" ///////////////////////////////////////////////////////////////////// ////////////////////---MODBUS FUNCTION DEFINES---//////////////////// //-------------------------------------------------- /** * @addtogroup MODBUS_COILS * @{ */ /** * @brief Макрос для установки указателя на регистр, содержащий запрашиваемый коил * @param _parr_ - массив коилов. * @param _coil_ - Номер коила от начала массива _arr_. * @note Используется вместе с @ref MB_Set_Coil_Mask @verbatim Пояснение выражений - (_coil_/16) - индекс регистра, в котором содержится коил по адресу _coil_ Визуальный пример: 30 коил будет в 30/16 = 1 регистре (индексация с 0) xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx |register[0]----| |register[1]----| |skip this------| |get this-------| |shift to 14 bit| @endverbatim */ #define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) /** * @brief Макрос для установки маски, чтобы выделить запрашиваемый коил из регистра * @param _coil_ - Номер коила от начала массива _arr_. * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr @verbatim Пояснение выражений - (16*(_coil_/16) - сколько коилов нужно пропустить. прим. (16*30/16) - первые 16 коилов находятся вне регистра - _coil_-(16*(_coil_/16)) - сдвинуть бит на место запрашиваемого коила в регистре Визуальный пример: 30 коил будет регистре[1], на 14 бите: register = 30/16 = 1 bit = 30 - (16*30/16) = 30 - 16 = 14 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx |register[0]----| |register[1]----| |skip this------| |get this-------| |shift to 14 bit| @endverbatim */ #define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) /** MODBUS_COILS * @} */ ///////////////////////////////////////////////////////////////////// /////////////////////////---FUNCTIONS---///////////////////////////// /** * @addtogroup MODBUS_REQ_COILS_API API for Coils * @ingroup MODBUS_REQUEST_MSG * @brief API для чтения coils из ответа в режиме мастер * @details Примеры использования: * * @code * // Пример: Запросили 10 coils с адреса 20, хотим узнать состояние coil 25 * int coil_state; * if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state)) * { * printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF"); * } * * // Пример: Получить состояние всех запрошенных coils * for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) * { * int state; * if(MB_RespGet_CoilState(&MODBUS_MSG, addr, &state)) * { * printf("Coil %d: %s\n", addr, state ? "ON" : "OFF"); * } * } * @endcode * @{ */ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state); /** MODBUS_REQ_COILS_API * @} */ /** * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access * @ingroup MODBUS_FUNCTIONS * @brief Функции для доступа к данным модбас * @{ */ /** @brief Structure for coils operation */ typedef enum { SET_COIL, RESET_COIL, TOOGLE_COIL, }MB_CoilsOpTypeDef; /** * @brief Считать коил по локальному адресу. * @param _parr_ - массив коилов. * @param _coil_ - Номер коила от начала массива _arr_. * @return uint16_t Возвращает запрошенный коил на 0м бите. * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ #define MB_Coil_Read_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) /** * @brief Выставить коил по локальному адресу. * @param _parr_ Указатель на массив коилов. * @param _coil_ - Номер коила от начала массива _arr_. * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ #define MB_Coil_Set_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) /** * @brief Сбросить коил по локальному адресу. * @param _parr_ Указатель на массив коилов. * @param _coil_ - Номер коила от начала массива _arr_. * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ #define MB_Coil_Reset_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) /** * @brief Переключить состояние коила по локальному адресу. * @param _parr_ Указатель на массив коилов. * @param _coil_ - Номер коила от начала массива _arr_. * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ #define MB_Coil_Toogle_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) /* Выставить/сбросить коил по глобальному адресу */ MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal); /* Считать коил по глобальному адресу */ uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); /** MODBUS_DATA_ACCESS_FUNCTIONS * @} */ //---------PROCESS MODBUS COMMAND FUNCTIONS--------- /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS @{ */ /* Обработать функцию Read Coils (01 - 0x01) */ uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg); /* Обработать функцию Write Single Coils (05 - 0x05) */ uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg); /* Обработать функцию Write Multiple Coils (15 - 0x0F) */ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); /** MODBUS_CMD_PROCESS_FUNCTIONS * @} */ /////////////////////////---FUNCTIONS---///////////////////////////// #endif //__MODBUS_COILS_H_ /** MODBUS_COILS * @} */