stm32的HAL庫uart的注意點


(一)、uart / usart 要注意的 API使用方法。

  1.__HAL_UART_GET_FLAG 是獲取 SR 寄存器標志位狀態

  2.__HAL_UART_CLEAR_FLAG 是清除 SR 寄存器標志位狀態,不同於讀改寫的清零方式,這是直接清零。

  3.__HAL_UART_CLEAR_xxFLAG ,xx為PE FE NE ORE IDLE 共5個, 清除方式都是一樣的,要先讀取SR,再讀取DR才能清除對應的標志位

  4.UART_Receive_IT或許有bug,tmp = (uint16_t*) huart->pRxBuffPtr;需要pRxBuffPtr十六位對齊,但是pRxBuffPtr類型是uint8_t *,是不一定對齊的。所以在聲明buffer的時候要注意聲明稱16位以上對齊的數據。

  5.SR不能用軟件置1,一般都是軟件清零,通過讀改寫方式清零會導致中斷請求丟失,推薦軟件直接寫0清除標志。

  6.注意UART_FLAG_xx和UART_IT_xx的區別

  7.串口發送只能一次,問題在於沒有開啟TC中斷

 

(二)串口的框圖需要理解透

 

 

 (三)代碼如下

 

接收不定長的數據

/**
  * @brief  This function handles UART interrupt request.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
void user_Uart1Handler(void)
{

    if ( (__HAL_UART_GET_FLAG (&huart1, UART_FLAG_RXNE) != RESET) )//接收數據
    {
        if (uart1RxCounter < 99)
        {
            uart1RxBuf[uart1RxCounter] =(char)( huart1.Instance->DR & 0xff);
            uart1RxCounter++;
        }
        __HAL_UART_CLEAR_FLAG (&huart1, UART_FLAG_RXNE);

    }

    if(__HAL_UART_GET_FLAG (&huart1, UART_FLAG_TXE) != RESET) //可以發送下個字節
    {
        __HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
        __HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);
    }

    if ( (__HAL_UART_GET_FLAG (&huart1, UART_FLAG_IDLE) != RESET) ) //接收完一幀數據,空閑標志
    {
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
        rx1_cplt = SET;
        huart1.RxState = HAL_UART_STATE_READY;
    }
    
    if ( (__HAL_UART_GET_FLAG (&huart1, UART_FLAG_TC) != RESET) ) //發送完一幀數據,TC標志
    {
        __HAL_UART_CLEAR_PEFLAG (&huart1);
        __HAL_UART_CLEAR_PEFLAG (&huart1);
        huart1.gState = HAL_UART_STATE_READY;
    }
    
    {
        uint32_t state;
        state = __HAL_UART_GET_FLAG (&huart1, UART_FLAG_PE)| __HAL_UART_GET_FLAG (&huart1, UART_FLAG_FE)\
        |__HAL_UART_GET_FLAG (&huart1, UART_FLAG_NE)|__HAL_UART_GET_FLAG (&huart1, UART_FLAG_ORE);
        if (state != RESET)
        {
            __HAL_UART_CLEAR_PEFLAG (&huart1);
            
        }
    }
    
    if(huart1.ErrorCode != HAL_UART_ERROR_NONE)
    {
        Error_Handler();
    }

}

printf回調 發送單個字節的程序如下,前提是打開dma和中斷:

 

void Uart_PutChar(UART_HandleTypeDef *huart, char ch)
{
    if(__HAL_UART_GET_FLAG (huart, UART_FLAG_TXE) != RESET)
    {
        huart->Instance->DR = (uint16_t)ch &    (uint16_t)0x01FF;//每次寫DR會清零TXE
        while(__HAL_UART_GET_FLAG(huart,UART_FLAG_TXE) != SET)
        {
        
        }
    }

}
void putchar_uart1_callback(char ch)
{  
    Uart_PutChar(&huart1,ch);
}

printf回調 ,發送多個字符串的程序如下,前提是打開dma和中斷:

void putstring_uart1_callback(char *data, unsigned int size)
{
    HAL_UART_Transmit_DMA(&huart1,(uint8_t *)data,size);
}

還要記得在main循環之前,打開相關中斷:
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
   
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);

    __HAL_UART_ENABLE_IT(&huart1, UART_IT_ERR);

    __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM