190 lines
8.3 KiB
C
190 lines
8.3 KiB
C
/**
|
||
******************************************************************************
|
||
* @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---////////////////////
|
||
|
||
/** @brief Structure for coils operation */
|
||
typedef enum
|
||
{
|
||
SET_COIL,
|
||
RESET_COIL,
|
||
TOOGLE_COIL,
|
||
}MB_CoilsOpTypeDef;
|
||
|
||
//--------------------------------------------------
|
||
|
||
/**
|
||
* @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)) ))
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||
|
||
/**
|
||
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access
|
||
* @ingroup MODBUS_FUNCTIONS
|
||
* @brief Функции для доступа к данным модбас
|
||
@{
|
||
*/
|
||
|
||
|
||
/**
|
||
* @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_GetCoilState(&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_GetCoilState(&MODBUS_MSG, addr, &state))
|
||
* {
|
||
* printf("Coil %d: %s\n", addr, state ? "ON" : "OFF");
|
||
* }
|
||
* }
|
||
* @endcode
|
||
*/
|
||
|
||
int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state);
|
||
|
||
/** MODBUS_REQ_COILS_API
|
||
* @}
|
||
*/
|
||
|
||
|
||
|
||
/**
|
||
* @brief Считать коил по локальному адресу.
|
||
* @param _parr_ - массив коилов.
|
||
* @param _coil_ - Номер коила от начала массива _arr_.
|
||
* @return uint16_t Возвращает запрошенный коил на 0м бите.
|
||
*
|
||
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
||
*/
|
||
#define MB_Read_Coil_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_Set_Coil_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_Reset_Coil_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_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
|
||
|
||
/* Выставить/сбросить коил по глобальному адресу */
|
||
MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal);
|
||
/* Считать коил по глобальному адресу */
|
||
uint16_t MB_Read_Coil_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_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
|
||
|
||
/** MODBUS_CMD_PROCESS_FUNCTIONS
|
||
* @}
|
||
*/
|
||
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||
|
||
#endif //__MODBUS_COILS_H_
|
||
|
||
/** MODBUS_COILS
|
||
* @}
|
||
*/ |