заработало чтение, надо привести в порядок код

This commit is contained in:
2025-08-28 21:52:11 +03:00
parent 2317b904ba
commit 51f6216eb7
4 changed files with 125 additions and 300 deletions

View File

@@ -57,55 +57,6 @@ uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
//-------------------------------------------------------------------
//-------------------------GENERAL FUNCTIONS-------------------------
/**
* @brief Start receive IT.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации приема.
*/
RS_StatusTypeDef RS_Receive_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) {
if (hRS->f.RS_Busy || hRS->f.RX_Busy) return RS_BUSY;
RS_EnableReceive();
RS_Set_Busy(hRS);
RS_Set_RX_Flags(hRS);
hRS->pMessagePtr = RS_msg;
hRS->lastByteTime = millis();
hRS->RS_STATUS = RS_OK;
return RS_OK;
}
/**
* @brief Start transmit IT.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации передачи.
*/
RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) {
if (hRS->f.RS_Busy || hRS->f.TX_Busy) return RS_BUSY;
RS_StatusTypeDef RS_RES = RS_Collect_Message(hRS, RS_msg, hRS->pBufferPtr);
if (RS_RES != RS_OK) {
RS_Abort(hRS, ABORT_RS);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
return RS_RES;
}
RS_EnableTransmit();
RS_Set_Busy(hRS);
RS_Set_TX_Flags(hRS);
hRS->pMessagePtr = RS_msg;
hRS->huart->write(hRS->pBufferPtr, hRS->RS_Message_Size);
hRS->lastByteTime = millis();
return RS_OK;
}
/**
* @brief Initialize UART and handle RS stucture.
* @param hRS - указатель на хендлер RS.
@@ -116,7 +67,10 @@ RS_StatusTypeDef RS_Transmit_IT(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) {
* @note Инициализация перефирии и структуры для приема-передачи по RS.
*/
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8_t *pRS_BufferPtr) {
if (!hRS || !SerialPort) return RS_ERR;
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;
@@ -126,29 +80,28 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8
RS_Reset_TX_Flags(hRS);
hRS->f.RX_Half = 0;
hRS->lastByteTime = millis();
hRS->lastByteTime = 0;
Serial.println("[RS] Initialized successfully");
return RS_OK;
}
/**
* @brief Abort RS/UART.
* @param hRS - указатель на хендлер RS.
* @param AbortMode - выбор, что надо отменить.
- ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX,
- ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX,
- ABORT_RX_TX: Отмена приема и передачи по ЮАРТ,
- ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры.
* @return RS_RES - статус о состоянии RS после аборта.
* @note Отмена работы UART в целом или отмена приема/передачи RS.
Также очищается хендл hRS.
*/
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) RS_Reset_RX_Flags(hRS);
if ((AbortMode & ABORT_TX) == ABORT_TX) RS_Reset_TX_Flags(hRS);
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);
}
@@ -157,179 +110,98 @@ RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) {
return RS_ABORTED;
}
//-------------------------GENERAL FUNCTIONS-------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//--------------------CALLBACK/HANDLER FUNCTIONS---------------------
/**
* @brief Handle for starting receive.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации приема или окончания общения.
* @note Определяет начинать прием команды/ответа или нет.
*/
RS_StatusTypeDef RS_Handle_Receive_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
RS_StatusTypeDef RS_RES = RS_OK;
switch(hRS->sRS_Mode)
{
case SLAVE_ALWAYS_WAIT: // in slave mode with permanent waiting
RS_RES = RS_Receive_IT(hRS, RS_msg); break; // start receiving again
case SLAVE_TIMEOUT_WAIT: // in slave mode with timeout waiting (start receiving cmd by request)
RS_Set_Free(hRS); RS_RES = RS_OK; break; // end RS communication (set RS unbusy)
}
if(RS_RES != RS_OK)
{
}
return RS_RES;
}
/**
* @brief Handle for starting transmit.
* @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации передачи.
* @note Определяет отвечать ли на команду или нет.
*/
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{
RS_StatusTypeDef RS_RES = RS_OK;
switch(hRS->sRS_Mode)
{
case SLAVE_ALWAYS_WAIT: // in slave mode always response
case SLAVE_TIMEOUT_WAIT: // transmit response
RS_RES = RS_Transmit_IT(hRS, RS_msg); break;
}
if(RS_RES != RS_OK)
{
}
return RS_RES;
}
/**
* @brief UART RX Callback: define behaviour after receiving parts of message.
* @param hRS - указатель на хендлер RS.
* @return RS_RES - статус о состоянии RS после обработки приема.
* @note Контролирует прием сообщения: определяет размер принимаемой посылки и обрабатывает его.
*/
RS_StatusTypeDef RS_UART_RxCpltCallback(RS_HandleTypeDef *hRS) {
if (!hRS->f.RX_Half && hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) {
hRS->f.RX_Half = 1;
uint32_t restSize = 0xFFFF;
RS_StatusTypeDef res = RS_Define_Size_of_RX_Message(hRS, &restSize);
if (res == RS_SKIP || restSize == 0xFFFF) {
RS_Abort(hRS, ABORT_RX);
return RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
}
// if there is no bytes to receive
if(NuRS_of_Rest_Bytes == 0)
{
hRS->f.RX_Half = 0;
//---------PROCESS DATA & ENDING RECEIVING--------
RS_Set_RX_End(hRS);
// parse received data
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
hRS->RS_Message_Size = NuRS_of_Rest_Bytes;
// RESPONSE
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
return RS_RES;
}
}
else // if we had received whole message
{
hRS->f.RX_Half = 0;
//---------PROCESS DATA & ENDING RECEIVING--------
RS_Set_RX_End(hRS);
// parse received data
RS_RES = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr); // parse message
// RESPONSE
RS_RES = RS_Response(hRS, hRS->pMessagePtr);
}
return RS_RES;
}
/**
* @brief UART TX Callback: define behaviour after transmiting message.
* @param hRS - указатель на хендлер RS.
* @return RS_RES - статус о состоянии RS после обработки приема.
* @note Определяет поведение RS после передачи сообщения.
*/
RS_StatusTypeDef RS_UART_TxCpltCallback(RS_HandleTypeDef *hRS)
{
RS_StatusTypeDef RS_RES = RS_OK;
HAL_StatusTypeDef uart_res = 0;
//--------------ENDING TRANSMITTING-------------
RS_Set_TX_End(hRS);
RS_EnableReceive();
// for(int i = 0; i < hRS->sRS_Timeout; i++);
//-----------START RECEIVING or END RS----------
RS_RES = RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
return RS_RES;
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;
}
/**
* @brief Handler for UART.
* @param hRS - указатель на хендлер RS.
* @note Обрабатывает ошибки если есть и вызывает RS Коллбеки.
* Добавить вызов этой функции в UARTx_IRQHandler() после HAL_UART_IRQHandler().
*/
void RS_UART_Handler(RS_HandleTypeDef *hRS) {
while (hRS->huart->available()) {
uint8_t b = hRS->huart->read();
hRS->pBufferPtr[hRS->RS_Message_Size++] = b;
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;
if (hRS->f.RX_Busy && (hRS->RS_Message_Size >= RX_FIRST_PART_SIZE) && !hRS->f.RX_Half)
RS_UART_RxCpltCallback(hRS);
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;
}
}
}
}
/**
* @brief Handler for TIM (timeout check).
* @param hRS - указатель на хендлер RS.
* @note Проверяет таймаут между байтами. Если превышен, сбрасывает RX и перезапускает прием.
* Вызывать в TIMx_IRQHandler() после HAL_TIM_IRQHandler().
*/
void RS_TIM_Handler(RS_HandleTypeDef *hRS) {
if (!hRS) return;
unsigned long now = millis();
// Если идет прием данных и есть таймаут
if (hRS->f.RX_Busy && hRS->sRS_Timeout > 0) {
if ((now - hRS->lastByteTime) >= hRS->sRS_Timeout) {
// таймаут истек → abort RX и restart
RS_Abort(hRS, ABORT_RX);
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
}
}
// Можно также проверять TX, если нужна логика таймаута передачи
if (hRS->f.TX_Busy && hRS->sRS_Timeout > 0) {
if ((now - hRS->lastByteTime) >= hRS->sRS_Timeout) {
RS_Abort(hRS, ABORT_TX);
// TX не рестартим автоматически
}
}
}
// weak functions