/** ****************************************************************************** * @file rs_message.h * @brief Библиотека обмена сообщениями по RS-интерфейсу ****************************************************************************** @defgroup RS_TOOLS RS Tools @brief Всякое для работы по UART/RS @{ ****************************************************************************** * @details Универсальная библиотека для работы с последовательными протоколами (Modbus, Custom) через UART в режиме прерываний с поддержкой таймаутов. @section Основные возможности: - Прием/передача в прерываниях - Обработка IDLE линии для определения конца фрейма - Таймауты приема через TIM - Гибкая настройка размера сообщений @section Использование: 1. Определить структуру сообщения и размеры буфера 2. Реализовать weak-функции обработки сообщений 3. Добавить вызовы RS_UART_Handler/RS_TIM_Handler в прерывания 4. Инициализировать через RS_Init() и запустить прием RS_Receive_IT() @section Особенности: - Буфер: RS_Buffer[MSG_SIZE_MAX] Общий для приема/передачи - Состояния: отслеживается через флаги в RS_HandleTypeDef - Таймауты: контролируют максимальное время ожидания фрейма ******************************************************************************/ #ifndef __RS_LIB_H_ #define __RS_LIB_H_ #include "modbus_core.h" ///////////////////////////////////////////////////////////////////// ////////////////////////////---DEFINES---//////////////////////////// /* Check that all defines required by RS are defined */ #ifndef MSG_SIZE_MAX #error Define MSG_SIZE_MAX (Maximum size of message). This is necessary to create buffer for UART. #endif #ifndef RX_FIRST_PART_SIZE #error Define RX_FIRST_PART_SIZE (Size of first part of message). This is necessary to receive the first part of the message, from which determine the size of the remaining part of the message. #endif /** * @cond Заглушки и внутренний недокументированный стаф */ /* Clear message-uart buffer */ #define RS_Clear_Buff(_buff_) for(int i=0; if.RS_Busy = 0 #define RS_Set_Busy(_hRS_) _hRS_->f.RS_Busy = 1 #define RS_Set_RX_Flags(_hRS_) _hRS_->f.RX_Busy = 1; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0 #define RS_Set_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 1 #define RS_Set_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 1; _hRS_->f.TX_Done = 0 #define RS_Reset_RX_Active_Flags(_hRS_) _hRS_->f.RX_Ongoing = 0; _hRS_->f.RX_Continue = 0; #define RS_Reset_RX_Flags(_hRS_) RS_Reset_RX_Active_Flags(_hRS_); _hRS_->f.RX_Busy = 0; _hRS_->f.RX_Done = 0; _hRS_->f.RX_Half = 0 #define RS_Reset_TX_Flags(_hRS_) _hRS_->f.TX_Busy = 0; _hRS_->f.TX_Done = 0 #define RS_Set_RX_End_Flag(_hRS_) _hRS_->f.RX_Done = 1; #define RS_Set_TX_End_Flag(_hRS_) _hRS_->f.TX_Done = 1 #define RS_Set_RX_End(_hRS_) RS_Reset_RX_Flags(_hRS_); RS_Set_RX_End_Flag(_hRS_) #define RS_Set_TX_End(_hRS_) RS_Reset_TX_Flags(_hRS_); RS_Set_TX_End_Flag(_hRS_) /* Clear all RS stuff */ #define RS_Clear_All(_hRS_) RS_Clear_Buff(_hRS_->pBufferPtr); RS_Reset_RX_Flags(_hRS_); RS_Reset_TX_Flags(_hRS_); //#define MB_Is_RX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_RX) //#define MB_Is_TX_Busy(_hRS_) ((_hRS_->huart->gState&HAL_USART_STATE_BUSY_RX) == HAL_USART_STATE_BUSY_TX) #define RS_Is_RX_Busy(_hRS_) (_hRS_->f.RX_Busy == 1) #define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1) // направление передачи rs485 #ifndef RS_EnableReceive #define RS_EnableReceive() #endif #ifndef RS_EnableTransmit #define RS_EnableTransmit() #endif #ifndef printf_rs_err #define printf_rs_err(...) #endif #ifndef printf_rs #define printf_rs(...) #endif #ifndef __MYLIBS_CONFIG_H_ // дефайны из mylibs include static int dummy; #define TrackerTypeDef(num_user_vars) void * #define num_of_usercnts(_user_) 0 #define assert_tracecnt(_cntstruct_, _uservarnumb_) 0 #define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(0) #define tern_assert_usertracker(_cntstruct_, _uservarnumb_) 0 #define TrackerGet_Ok(_cntstruct_) dummy #define TrackerGet_Err(_cntstruct_) dummy #define TrackerGet_Warn(_cntstruct_) dummy #define TrackerGet_User(_cntstruct_, _uservarnumb_) dummy #define TrackerCnt_Ok(_cntstruct_) #define TrackerCnt_Err(_cntstruct_) #define TrackerCnt_Warn(_cntstruct_) #define TrackerCnt_User(_cntstruct_, _uservarnumb_) #define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) #define TrackerClear_All(_cntstruct_) #define TrackerClear_Ok(_cntstruct_) #define TrackerClear_Err(_cntstruct_) #define TrackerClear_Warn(_cntstruct_) #define TrackerClear_User(_cntstruct_) #define TrackerClear_UserAll(_cntstruct_) #else #include "mylibs_include.h" #endif #ifndef RS_USER_VARS_NUMB #define RS_USER_VARS_NUMB 0 #endif /** @endcond */ ////////////////////////////---DEFINES---//////////////////////////// ///////////////////////////////////////////////////////////////////// ///////////////////////---STRUCTURES & ENUMS---////////////////////// //------------------ENUMERATIONS-------------------- /** @brief Enums for respond CMD about RS status */ typedef enum // RS_StatusTypeDef { /* IN-CODE STATUS (start from 0x01, and goes up)*/ /*0x01*/ RS_OK = 0x01, /*0x02*/ RS_ERR, /*0x03*/ RS_ABORTED, /*0x04*/ RS_BUSY, /*0x05*/ RS_SKIP, /*0x06*/ RS_COLLECT_MSG_ERR, /*0x07*/ RS_PARSE_MSG_ERR, // reserved values // /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero) }RS_StatusTypeDef; #define RS_MASTER_START 0x3 /** @brief Enums for RS Modes */ typedef enum // RS_ModeTypeDef { RS_SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting RS_SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout // RS_MASTER = 0x03, ///< Master mode }RS_ModeTypeDef; /** @brief Enums for RS UART Modes */ typedef enum // RS_ITModeTypeDef { BLCK_MODE = 0x00, ///< Blocking mode IT_MODE = 0x01, ///< Interrupt mode }RS_ITModeTypeDef; /** @brief Enums for Abort modes */ typedef enum // RS_AbortTypeDef { ABORT_TX = 0x01, ///< Abort transmit ABORT_RX = 0x02, ///< Abort receive ABORT_RX_TX = 0x03, ///< Abort receive and transmit ABORT_RS = 0x04, ///< Abort uart and reset RS structure }RS_AbortTypeDef; /** @brief Enums for RX Size modes */ typedef enum // RS_RXSizeTypeDef { RS_RX_Size_Const = 0x01, ///< size of receiving message is constant RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant }RS_RXSizeTypeDef; //-----------STRUCTURE FOR HANDLE RS------------ /** @brief Struct for flags RS */ typedef struct { unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done // setted by user unsigned RX_Continue:1; ///< flag: 0 - continue receiving, 0 - start receiving from ind = 0 unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt unsigned DataUpdated:1; ///< flag: 1 - Received command to write colis/resg unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing }RS_FlagsTypeDef; /** * @brief Handle for RS communication. * @note Prefixes: h - handle, s - settings, f - flag */ typedef struct // RS_HandleTypeDef { /* MESSAGE */ uint8_t ID; ///< ID of RS "channel" RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct uint8_t *pBufferPtr; ///< pointer to message buffer int32_t RS_Message_Size; ///< size of whole message, not only data /* HANDLERS and SETTINGS */ UART_HandleTypeDef *huart; ///< handler for used uart TIM_HandleTypeDef *htim; ///< handler for used tim RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef RS_ITModeTypeDef sRS_IT_Mode; ///< setting: 1 - IT mode, 0 - Blocking mode uint16_t sRS_Timeout; ///< setting: timeout in ms RS_RXSizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const /* FLAGS */ RS_FlagsTypeDef f; ///< These flags for controling receive/transmit /* RS STATUS */ uint32_t lastPacketTick; RS_StatusTypeDef RS_STATUS; ///< RS status TrackerTypeDef(RS_USER_VARS_NUMB) rs_err; }RS_HandleTypeDef; extern RS_HandleTypeDef hmodbus1; ///////////////////////---STRUCTURES & ENUMS---////////////////////// ///////////////////////////////////////////////////////////////////// ///////////////////////////---FUNCTIONS---/////////////////////////// //----------------FUNCTIONS FOR PROCESSING MESSAGE------------------- /*--------------------Defined by users purposes--------------------*/ /* Respond accord to received message */ RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); /* Collect message in buffer to transmit it */ RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff); /* Parse message from buffer to process it */ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff); //-------------------------GENERAL FUNCTIONS------------------------- /*-----------------Should be called from main code-----------------*/ /* Start receive IT */ RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); /* Start transmit IT */ RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); /* Initialize UART and handle RS stucture */ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, uint8_t *pRS_BufferPtr); /* ReInitialize UART and RS receive */ HAL_StatusTypeDef RS_ReInit_UART(RS_HandleTypeDef *hRS, UART_HandleTypeDef *suart); /* Abort RS/UART */ RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode); //-------------------------GENERAL FUNCTIONS------------------------- //------------------------------------------------------------------- //--------------------CALLBACK/HANDLER FUNCTIONS--------------------- /* Handle for starting receive */ RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); /* Handle for starting transmit */ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg); /* UART TX Callback: define behaviour after transmiting message */ RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS); /* Handler for UART */ void RS_UART_Handler(RS_HandleTypeDef *hRS); /* Handler for TIM */ void RS_TIM_Handler(RS_HandleTypeDef *hRS); //--------------------CALLBACK/HANDLER FUNCTIONS--------------------- ///////////////////////////---FUNCTIONS---/////////////////////////// /** RS_TOOLS * @} */ #endif // __RS_LIB_H_