/** ************************************************************************** * @file rs_message.c * @brief Модуль для реализации протоколов по RS/UART. **************************************************************************\ * @details * Данный модуль реализует основные функции для приема и передачи сообщений * по протоколу RS через UART в режиме прерываний. Реализована обработка * приема и передачи данных, управление состояниями RS, а также функции для * инициализации и управления периферией. * * Реализованы следующие функции: * - RS_Receive_IT() — запуск приема данных в прерывании по UART. * - RS_Transmit_IT() — запуск передачи данных в прерывании по UART. * - RS_Init() — инициализация структуры RS и привязка периферии. * - RS_ReInit_UART() — переинициализация UART и перезапуск приема данных. * - RS_Abort() — остановка работы RS/UART с очисткой флагов и структур. * - RS_Handle_Receive_Start() — обработка старта приема данных по RS. * * В модуле также определен буфер RS_Buffer[] для хранения принимаемых/передаваемых данных. * * @note * Для корректной работы модуля предполагается использование соответствующих * обработчиков прерываний UART и таймера (RS_UART_Handler(), RS_TIM_Handler()), * которые надо вызывать с обработчиках используемой периферии @verbatim //-------------------Функции-------------------// Functions: users - RS_Parse_Message/RS_Collect_Message Заполнение структуры сообщения и буфера - RS_Response Ответ на сообщение - RS_Define_Size_of_RX_Message Определение размера принимаемых данных Functions: general - RS_Receive_IT Ожидание комманды и ответ на неё - RS_Transmit_IT Отправление комманды и ожидание ответа - RS_Init Инициализация переферии и структуры для RS - RS_ReInit_UART Реинициализация UART для RS - RS_Abort Отмена приема/передачи по ЮАРТ - RS_Init Инициализация периферии и modbus handler Functions: callback/handler - RS_Handle_Receive_Start Функция для запуска приема или остановки RS - RS_Handle_Transmit_Start Функция для запуска передачи или остановки RS - RS_UART_RxCpltCallback Коллбек при окончании приема или передачи RS_UART_TxCpltCallback - RS_UART_Handler Обработчик прерывания для UART - RS_TIM_Handler Обработчик прерывания для TIM @endverbatim *************************************************************************/ #include "rs_message.h" uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer //------------------------------------------------------------------- //-------------------------GENERAL FUNCTIONS------------------------- /** * @brief Initialize UART and handle RS stucture. * @param hRS - указатель на хендлер RS. * @param suart - указатель на структуру с настройками UART. * @param stim - указатель на структуру с настройками таймера. * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. * @return RS_RES - статус о состоянии RS после инициализации. * @note Инициализация перефирии и структуры для приема-передачи по RS. */ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8_t *pRS_BufferPtr) { if (!hRS || !SerialPort) { Serial.println("[RS] Init error: null handler or port"); return RS_ERR; } hRS->huart = SerialPort; hRS->pBufferPtr = pRS_BufferPtr ? pRS_BufferPtr : RS_Buffer; hRS->RS_STATUS = RS_OK; RS_Set_Free(hRS); RS_Reset_RX_Flags(hRS); RS_Reset_TX_Flags(hRS); hRS->f.RX_Half = 0; hRS->lastByteTime = 0; Serial.println("[RS] Initialized successfully"); return RS_OK; } RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) { if (hRS == nullptr) { Serial.println("[RS] Abort error: null handler"); return RS_ERR; } if ((AbortMode & ABORT_RS) == 0) { if ((AbortMode & ABORT_RX) == ABORT_RX) { Serial.println("[RS] Abort RX"); RS_Reset_RX_Flags(hRS); } if ((AbortMode & ABORT_TX) == ABORT_TX) { Serial.println("[RS] Abort TX"); RS_Reset_TX_Flags(hRS); } } else { Serial.println("[RS] Abort RS (full reset)"); RS_Clear_All(hRS); } RS_Set_Free(hRS); hRS->RS_STATUS = RS_ABORTED; return RS_ABORTED; } RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { if (hRS == nullptr || RS_msg == nullptr) { Serial.println("[RS] TX start error: null ptr"); return RS_ERR; } if (RS_Is_TX_Busy(hRS)) { Serial.println("[RS] TX busy, cannot start"); return RS_BUSY; } RS_StatusTypeDef status = RS_Collect_Message(hRS, RS_msg, hRS->pBufferPtr); if (status != RS_OK) { Serial.println("[RS] TX collect message failed"); return status; } Serial.print("[RS] TX start, size="); Serial.println(hRS->RS_Message_Size); RS_Set_TX_Flags(hRS); hRS->huart->write(hRS->pBufferPtr, hRS->RS_Message_Size); RS_Set_TX_End(hRS); Serial.println("[RS] TX finished"); return RS_OK; } void RS_Process(RS_HandleTypeDef *hRS) { if (hRS == nullptr) { Serial.println("[RS] Process error: null handler"); return; } static uint32_t rx_index = 0; static uint32_t expected_size = RX_FIRST_PART_SIZE; if (hRS->f.RX_Ongoing) { if (millis() - hRS->lastByteTime > hRS->sRS_Timeout) { Serial.println("[RS] RX timeout"); RS_Abort(hRS, ABORT_RX); return; } } if (hRS->huart->available()) { if (!hRS->f.RX_Ongoing) { Serial.println("[RS] RX start"); RS_Set_RX_Active_Flags(hRS); rx_index = 0; expected_size = RX_FIRST_PART_SIZE; RS_Clear_Buff(hRS->pBufferPtr); } hRS->lastByteTime = millis(); while (hRS->huart->available() && rx_index < MSG_SIZE_MAX) { uint8_t b = hRS->huart->read(); hRS->pBufferPtr[rx_index++] = b; Serial.print("[RS] RX byte: 0x"); Serial.println(b, HEX); if (rx_index == RX_FIRST_PART_SIZE && hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) { uint32_t data_size; Serial.println("Defining size..."); RS_Define_Size_of_RX_Message(hRS, &data_size); expected_size = RX_FIRST_PART_SIZE + data_size; Serial.print("[RS] RX expected size="); Serial.println(expected_size); } if (rx_index >= expected_size) { RS_Set_RX_End(hRS); Serial.println("[RS] RX complete, parsing..."); RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); if (hRS->pMessagePtr->MbAddr == hRS->ID) { Serial.println("[RS] RX for me, sending response"); RS_Response(hRS, hRS->pMessagePtr); } else { Serial.print("[RS] RX not for me, Addr="); Serial.println(hRS->pMessagePtr->MbAddr); } break; } } } } // weak functions __attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) { return RS_ERR; }