STM32F4 HAL庫 UART相關API介紹

STM32F4 HAL庫 UART相關API介紹

本文絕大部分翻譯自ST的官方用戶手冊 Description of STM32F4 HAL and LL drivers

USART 與 UART 的區別在於有沒有同步通訊的功能。
USART: 通用同步異步收發器 ; UART: 通用異步收發器。緩存

當進行異步通訊時,這二者是沒有區別的。
這個同步通訊功能能夠把USART當作SPI來用,好比用USART來驅動SPI設備。異步

同步(阻塞模式)是指:發送方發出數據後,等接收方發回響應之後才發下一個數據包的通信方式。
異步(非阻塞模式)是指:發送方發出數據後,不等接收方發回響應,接着發送下個數據包的通信方式。ide

其中SPI IIC爲同步通訊 UART爲異步通訊, usart爲同步&異步通訊。函數

參考:https://blog.csdn.net/anbaixi...ui

硬件相關知識

STM32F427/STM32F429 共有4個USART與4個UART,以下表.net

序號 U(S)ART_RX引腳 U(S)ART_TX引腳 U(S)ART_CK引腳 USART_ CTS引腳 USART_ RTS引腳
USART1 PA10 PA9 PA8 PA11 PA12
USART2 PA3/PD6 PA2/PD5 PA4/PD7 PA0/PD3 PA1/PD4
USART3 PB11/PC11/PD9 PB10/PC10/PD8 PB12/PC12/PD10 PB13/PD11 PB14/PD12
UART4 PA1/PC11 PA0/PC10
UART5 PD2 PC12
USART6 PC7/PG9 PC6/PG14 PC8/PG7 PG13/PG15 PG8/PG12
UART7 PE7 PE8
UART8 PE0 PE1
RT: Receive Data 接收數據
TX: Transmit Data 發送數據
CK: Clock (同步)時鐘

硬件流控制翻譯

RTS: Request To Send 請求發送數據
CTS: Clear To Send 容許發送數據指針

參見: UART通訊中流控RTS和CTS的理解 https://blog.csdn.net/u013797...code

相關結構體變量

USRT_InitTypeDef

  • 該結構體定義了用於初始化UART的一些相關參數
typedef struct
{
  uint32_t BaudRate;  //波特率
  uint32_t WordLength;//字長 取值參考 UART_Word_Length 宏定義              
  uint32_t StopBits;  //中止位 取值參考 UART_Stop_Bits 宏定義         
  uint32_t Parity;    //奇偶校驗模式 取值參考 UART_Parity 宏定義 
  uint32_t Mode;      //收發模式 取值參考 UART_Mode 宏定義                
  uint32_t HwFlowCtl; //是否打開硬件流控制 取值參考 UART_Hardware_Flow_Control 宏定義                 
  uint32_t OverSampling;//是否打開過採樣模式 取值參考 UART_Over_Sampling 宏定義            .
}UART_InitTypeDef;

UART_HandleTypeDef

  • 該結構體定義的則是UART句柄(我的理解爲用於操做UART)的一些參數
  • 該結構體中只有*InstanceInit兩個成員變量是須要咱們配置的
typedef struct
{
  USART_TypeDef                 *Instance;        /*!< UART registers base address        */
                                                  // UART/USART相關寄存器的地址 已經在HAL庫中定義完 參數爲 U(S)ARTx x=1...8 
  UART_InitTypeDef              Init;             /*!< UART communication parameters      */
                                                  // UART初始化參數結構體
  uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */
                                                  // 緩存指針
  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
                                                  // 緩存指針指向的數據的大小(字節)
  uint16_t                      TxXferCount;      /*!< UART Tx Transfer Counter           */
                                                  // 緩存指針指向的數據的的數量(字節)
  uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */
  uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */
  uint16_t                      RxXferCount;      /*!< UART Rx Transfer Counter           */  
  DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      *
                                                    // DMA句柄
  DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */
  HAL_LockTypeDef               Lock;             /*!< Locking object                     */
                                                  // 鎖對象
  __IO HAL_UART_StateTypeDef    State;            /*!< UART communication state           */
                                                  // UART通訊狀態
  __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */
                                                  // 錯誤碼
}UART_HandleTypeDef;
  • HAL Locked The HAL lock is used by all HAL APIs to prevent accessing by accident shared resources.
    HAL庫中的API經過該參數來判斷某個API是否正在執行,如__HAL_LOCK(__HANDLE__)__HAL_UNLOCK(__HANDLE__)所實現的orm

    typedef enum { 
        HAL_UNLOCKED = 0x00, /*!<Resources unlocked*/ 
        HAL_LOCKED = 0x01 /*!< Resources locked */ 
    }HAL_LockTypeDef;
    #define __HAL_LOCK(__HANDLE__)                                           \
                                    do{                                        \
                                        if((__HANDLE__)->Lock == HAL_LOCKED)   \
                                        {                                      \
                                           return HAL_BUSY;                    \
                                        }                                      \
                                        else                                   \
                                        {                                      \
                                           (__HANDLE__)->Lock = HAL_LOCKED;    \
                                        }                                      \
                                      }while (0)
    #define __HAL_UNLOCK(__HANDLE__)                                          \
                                      do{                                       \
                                          (__HANDLE__)->Lock = HAL_UNLOCKED;    \
                                        }while (0)

使用方法

  1. 聲明 UART_HandleTyperDef 句柄結構體
  2. 使用HAL_UART_MspInit()初始化 UART 的底層資源

    1. 打開 USARTx 接口的時鐘
    2. 配置 UART 引腳

      1. 開啓 GPIO 時鐘
      2. 配置引腳模式爲 複用上拉
    3. 若是使用了中斷須要配合 NVIC 中斷優先級

      1. 配置優先級
      2. 啓動 NVIC USART IRQ 句柄
    4. 若是使用了DMA處理須要配置DMA

      1. 爲 輸入流 或 輸出流 聲明DMA句柄
      2. 開啓DMAx接口的時鐘
      3. 配置DMA句柄結構體的參數
      4. 配置DMA的輸入輸出流
      5. 將DMA句柄與UART DMA Tx/Rx句柄關聯
      6. 配置並啓用 NVIC
  3. 配置 UART 通訊的上層參數,包括波特率、字長、中止位等
  4. 根據不一樣的工做模式調用不一樣的初始化函數HAL_UART_Init() 異步通訊 HAL_HalfDuplex_Init() 半雙工通訊HAL_LIN_Init() LIN總線通訊HAL_MultiProcessor_Init() 多處理器通訊

相關函數API介紹

初始化類函數

  1. HAL_StatusTypeDef HAL_UART_Init (UART_HandleTypeDef * huart)
  2. HAL_StatusTypeDef HAL_HalfDuplex_Init (UART_HandleTypeDef * huart)
  3. HAL_StatusTypeDef HAL_LIN_Init (UART_HandleTypeDef * huart, uint32_t BreakDetectLength)
  4. HAL_StatusTypeDef HAL_MultiProcessor_Init (UART_HandleTypeDef * huart, uint8_t Address, uint32_t WakeUpMethod)
  5. HAL_StatusTypeDef HAL_UART_DeInit (UART_HandleTypeDef * huart)
  • UART上層參數的初始化/註銷函數,根據工做模式選用相應的初始化函數
  • 須要配置的參數包括 波特率、字長、中止位、奇偶校驗模式、是否開啓硬件流控制、收發模式、過採樣模式
  • 參數說明:

    • *huart UART句柄結構體的指針
  • 返回API的執行狀況,調用時注意檢查
  1. void HAL_UART_MspInit (UART_HandleTypeDef * huart)
  2. void HAL_UART_MspDeInit (UART_HandleTypeDef * huart)
  • UART底層參數的初始化/註銷函數,具體配置內容見使用方法說明
  • 在代碼移植時修改該配置初始化函數便可

輪詢(Polling)模式的IO操做

  1. HAL_StatusTypeDef HAL_UART_Transmit (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
  2. HAL_StatusTypeDef HAL_UART_Receive (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
  • 用於接收與發送數據
  • 阻塞模式,在接收、發送數據時沒法進行其餘操做
  • 參數說明:

    • *huart: UART句柄,用於操做UART
    • *pData: 緩衝區指針
    • Size: 緩衝區大小(以字節爲單位)
    • Timeout: 超時時間,不可能讓程序一直等待數據接收或發送,超過這個時間以後將放棄發送或接收
  • 返回該API的執行狀態

中斷模式的IO操做

  1. HAL_StatusTypeDef HAL_UART_Transmit_IT (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
  2. HAL_StatusTypeDef HAL_UART_Receive_IT (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
  • 用於開啓UART接收/發送中斷,這兩個函數會設置發送/接收的緩衝區地址,大小,數量而且開啓相應的中斷
  • 參數說明:

    • *huart: UART句柄,用於操做UART
    • *pData: 緩衝區指針
    • Size: 緩衝區大小(以字節爲單位)
  • 返回該API的執行狀態,調用時注意檢查

HAL_UART_Receive_IT()爲例

/**
  * @brief  Receives an amount of data in non blocking mode 
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be received
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  uint32_t tmp = 0;
  tmp = huart->State;  
  if((tmp == HAL_UART_STATE_READY) || (tmp == HAL_UART_STATE_BUSY_TX))
  {
    if((pData == NULL ) || (Size == 0)) 
    {
      return HAL_ERROR;
    }
    /* Process Locked */
    __HAL_LOCK(huart);
    
    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    huart->RxXferCount = Size;
    
    huart->ErrorCode = HAL_UART_ERROR_NONE;
    /* Check if a transmit process is ongoing or not */
    if(huart->State == HAL_UART_STATE_BUSY_TX) 
    {
      huart->State = HAL_UART_STATE_BUSY_TX_RX;
    }
    else
    {
      huart->State = HAL_UART_STATE_BUSY_RX;
    }
    
    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);
    
    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
    
    /* Process Unlocked */
    __HAL_UNLOCK(huart);
    
    /* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
    
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY; 
  }
}
  1. void HAL_UART_IRQHandler (UART_HandleTypeDef * huart)
  • UART中斷處理的公共函數,須要用戶在中斷處理函數void USARTx_IRQHandler()中調用該函數,或者能夠由STM32CubeMX程序自動生成。
  • 該函數會遍歷全部與UART有關的中斷類型並判斷是否發生錯誤(設置錯誤代碼),若沒有發生錯誤則進行發送/接收操做
  • 若發生錯誤會調用 回調函數HAL_UART_ErrorCallback()
  • 發送完成將調用 回掉函數HAL_UART_TxCpltCallback()
  • 接收完成(接收緩衝區滿)將調用會 回調函數HAL_UART_RxCpltCallback() ,若不想關閉接收須要在該回調函數中從新開啓接收中斷HAL_UART_Receive_IT()
/**
  * @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 HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t tmp1 = 0, tmp2 = 0;

  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_PE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE);  
  /* UART parity error interrupt occurred ------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_PEFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_PE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_FE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART frame error interrupt occurred -------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_FEFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_FE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_NE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART noise error interrupt occurred -------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_NEFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_NE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART Over-Run interrupt occurred ----------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    __HAL_UART_CLEAR_OREFLAG(huart);
    
    huart->ErrorCode |= HAL_UART_ERROR_ORE;
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
  /* UART in mode Receiver ---------------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  { 
    UART_Receive_IT(huart);
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE);
  /* UART in mode Transmitter ------------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  {
    UART_Transmit_IT(huart);
  }
  
  tmp1 = __HAL_UART_GET_FLAG(huart, UART_FLAG_TC);
  tmp2 = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC);
  /* UART in mode Transmitter end --------------------------------------------*/
  if((tmp1 != RESET) && (tmp2 != RESET))
  {
    UART_EndTransmit_IT(huart);
  }

  if(huart->ErrorCode != HAL_UART_ERROR_NONE)
  {
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
    
    HAL_UART_ErrorCallback(huart);
  }  
}

總結一下中斷模式下HAL庫實現UART通訊的流程

  1. 調用HAL_UART_Init()初始化UART(該函數會調用HAL_UART_MspInit()來初始化底層服務)
  2. 調用HAL_UART_Receive/Transmit_IT()準備開始接收或者發送數據
  3. 每接收/發送一個字節的數據時便會觸發中斷服務函數USARTx_IRQHandler()
  4. 中斷服務函數中調用中斷公共函數HAL_UART_IRQHandler()
  5. 檢查沒有錯誤後按照條件調用UART_Receive_IT() UART_Transmit_IT() UART_EndTransmit_IT()三個函數中的一個,當發送/接收完成後調用相應的回調函數(根據HAL_UART_Receive/Transmit_IT()的size參數來判斷是否完成發送/接收)
  6. 若發生錯誤則調用處理錯誤的回調函數。
  • 其中須要用戶實現的函數只有UARTx的中斷服務函數與相應的回調函數

如要提升程序執行的效率能夠重寫USARTx的中斷服務函數,無需調用UART中斷的公共接口而自行更具相應的標識來處理接收或發送的流程。

DMA模式的IO操做

  1. HAL_StatusTypeDef HAL_UART_Transmit_DMA (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
  2. HAL_StatusTypeDef HAL_UART_Receive_DMA (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)6
  • DMA模式下的發送/接收API
  • 非阻塞模式

UART外設狀態函數

  1. HAL_UART_StateTypeDef HAL_UART_GetState (UART_HandleTypeDef * huart)
  2. uint32_t HAL_UART_GetError (UART_HandleTypeDef * huart)
  • 分別獲取UART的狀態與錯誤代碼(宏定義)

宏定義介紹

具體參見stm32f4xx_hal.h頭文件

相關文章
相關標籤/搜索