1. 程式人生 > >STM32的CubeMX關於串列埠中斷接收

STM32的CubeMX關於串列埠中斷接收

C語言

作為剛工作不久的小白,剛接觸STM32的HAL庫,工作中使用到了,就記錄下自己遇到的問題,希望看到的大佬多多指教。

1、關於串列埠的初始化函式:

    MX_USART2_UART_Init()---波特率、奇偶校驗等配置

            HAL_UART_Init()---會將 huart->RxState = HAL_UART_STATE_READY;

    HAL_UART_MspInit()---GPIO,中斷優先順序等配置

2、當需要使用中斷接收時需要呼叫

    HAL_UART_Receive_IT()---配置接收的緩衝區指標,數量,huart->RxState = HAL_UART_STATE_BUSY_RX;,最後使能相應中斷

3、當中斷髮生時,執行

    HAL_UART_IRQHandler()--判斷中斷的型別,在此處我用到的是非空中斷,那麼會繼續呼叫UART_Receive_IT(huart);

    這個函式會首先判斷串列埠的接收狀態huart->RxState == HAL_UART_STATE_BUSY_RX,若果為真就進行資料的儲存,進 如     果達到規定的傳輸數量就會關閉中斷,改變huart->RxState = HAL_UART_STATE_READY;然後執行HAL_UART_RxCpltCallback();如果不為真,就清除接收中斷標誌。

4、HAL_UART_RxCpltCallback()這個函式裡儘可能的少些程式碼否則影響效率,如果想再次開啟中斷,可以在這裡呼叫       HAL_UART_Receive_IT(),進行再次接收

下面說說我遇到的問題:

初始化串列埠完畢後,呼叫一次HAL_UART_Receive_IT(&huart2,uxComDMA.ucRxBuf,ONE_BYTE),進行一個位元組的中斷接收,然後在HAL_UART_RxCpltCallback()函式裡,進行幀頭的校驗和傳輸數量的計算,然後繼續開啟。程式碼如下

           //如果計算的數量大於規定的數量,說明傳輸出錯。丟棄,判定上位機發送是否錯誤
            if(usRecLength > DMA_BUF_MAX)
            {
                uxComDMA.ucRxBuf[eMsg_DTH] = APP_NULL;
                uxComDMA.ucRxBuf[eMsg_DTL] = APP_NULL;
                uxComDMA.usRxLen = APP_NULL;
                PTCL_Dbg("計算數量大於規定數量");
            }
            //接收的數量大於等於計算的數量
            if(uxComDMA.usRxLen >= usRecLength)
            {
                uxComDMA.uxReceiveFlag = eAppTrue;//標記接收完成。---此時不再呼叫HAL_UART_Receive_IT()
            }
            else//繼續接受下一個資料
            {
                HAL_UART_Receive_IT(&huart2, uxComDMA.ucRxBuf+uxComDMA.usRxLen,ONE_BYTE);

            }

當正確接收一幀資料後,便不再開啟,直到這一陣資料處理完,主程式再次呼叫HAL_UART_Receive_IT()進行下一輪的接收。

那麼問題來了:規定的協議是8個位元組,在正確接收到8個位元組後便不再開啟中斷接收,主函式執行資料幀的處理完畢後才會開啟。但是如果上位機一次一共傳送了10個位元組,前8個位元組是正確的一幀,後面2個無用。當下位機接收到8個位元組便關閉了中斷,處理完後再次開啟。然後上位機再發來資料,發現下位機再也不能執行HAL_UART_RxCpltCallback(),協議就報廢了。

除錯後發現,後來接收資料時雖然可以進入中斷並且執行了UART_Receive_IT();但是huart->RxState 的值不是HAL_UART_STATE_BUSY_RX導致不能繼續執行傳輸完成回撥。疑問是,最後一次開啟中斷接收時呼叫HAL_UART_Receive_IT()函式確實將 huart->RxState = HAL_UART_STATE_BUSY_RX;

PTCL_Dbg("初始化接收的狀態%d",HAL_UART_Receive_IT(&huart2,uxComDMA.ucRxBuf,ONE_BYTE));//串列埠2的接收中斷

                                                                                                                                                       函式返回值為HAL_OK

PTCL_Dbg("串列埠的接收狀態%#x\r\n",huart2.RxState);----確實不等於HAL_UART_STATE_BUSY_RX,而是等於                                                                                                                                                   HAL_UART_STATE_READY

//    huart2.RxState = HAL_UART_STATE_BUSY_RX; ----加上這句話,可以解決問題


這是為什呢?

解決上述問題:

關於上述問題的總結:後兩個位元組傳輸時,已經關閉了中斷,但是硬體將ORE位(溢位標誌,看資料手冊)置一和RXNE位置一。當呼叫HAL_UART_Receive_IT()函式時,會同時使能EIE、PEIE、RXNEIE三個中斷。第一次我手動將RXNE位清除,但是沒有清除ORE位,造成呼叫就會立即產生中斷(溢位中斷)。當執行HAL_UART_IRQHandler()函式時:      

   



關於HAL庫,更多的是考慮到安全性和相容性所以程式碼量比較大,一開始使用不會像我們使用暫存器那麼隨意,所以必須深入看原始碼,才能更好的使用。