1. 程式人生 > >STM32cubemx-HAL庫串列埠斷線問題

STM32cubemx-HAL庫串列埠斷線問題

STM32cubemx:version5.1

Chip: STM32F446RE

IDE:Keil5

Q:小專案上寫了個簡單的通訊包,波特率230400,資料量較大1600Byte/s,DMA的方式實現接收,量產後發現跑久了部分機器會有隻能傳送不能接收的問題。

查了很久沒查到。中間加了斷線檢測,重新初始化串列埠,卻無法解決。最後面發現,HAL的鍋。

 

部分程式碼:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{        
    if(huart->Instance == UART4) {
           uint8_t ret=HAL_OK;
        if(frame_in_sync) {
            if(UART_Rx_Buffer.head == 0x55 && UART_Rx_Buffer.end == 0xAA) { // TODO: check check-sum
                UART_Rx_Data = UART_Rx_Buffer;
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer));
                uart_updata_time= HAL_GetTick();
                            
            } else { // frame not in sync, drop coming bytes until read an end(0xAA)
                frame_in_sync = 0;
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1);
            }
        } else {
              if( *(uint8_t *)&UART_Rx_Buffer == 0xAA) {
                frame_in_sync = 1;
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer));
            } else {
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1);
            }
        }
    }
}

上述的程式碼絕大多數時間都能夠正常執行。但是,總會出現莫名奇妙的掉線問題。並且難以複線。查了好久,看到有類似的問題,HAL庫會不處理異常的行為,要使用者處理。

在某些情況下,HAL_UART_Receive_IT 並沒有成功執行,返回了busy 或者erro,這時候整個流程就背打斷了。並且串列埠還會被莫名其妙鎖上。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{        
    if(huart->Instance == UART4) {
                uint8_t ret=HAL_OK;
        if(frame_in_sync) {
            if(UART_Rx_Buffer.head == 0x55 && UART_Rx_Buffer.end == 0xAA) { // TODO: check check-sum
                UART_Rx_Data = UART_Rx_Buffer;
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer));
                uart_updata_time= HAL_GetTick();
                            
            } else { // frame not in sync, drop coming bytes until read an end(0xAA)
                frame_in_sync = 0;
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1);
            }
        } else {
            if( *(uint8_t *)&UART_Rx_Buffer == 0xAA) {
                frame_in_sync = 1;
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer));
            } else {
                ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1);
            }
        }
                while(ret!=HAL_OK){
                     /*try to fix connection bug  20191225*/
                      printf("UART4:RECEIVE_IT:%d\r\n",ret);  //for log 
                      huart->RxState = HAL_UART_STATE_READY;
                      __HAL_UNLOCK(huart);
                      ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1); 
                }
    }
}


void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
    if(huart->ErrorCode&HAL_UART_ERROR_ORE)
    {
        __HAL_UART_CLEAR_OREFLAG(huart);
    }
  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_UART_ErrorCallback can be implemented in the user file.
   */
}

修改後,出現busy或者erro時強制解鎖,重新接收。根據log,大約半小時會出現一次。三臺經常性出現的機子更新後執行一天,沒有出現這個問題。在log中檢視到了對應的修正過