本文絕大部分翻譯自ST的官方用戶手冊 Description of STM32F4 HAL and LL driversUSART 與 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
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
*Instance
與Init
兩個成員變量是須要咱們配置的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__)
所實現的ormtypedef 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)
UART_HandleTyperDef
句柄結構體使用HAL_UART_MspInit()
初始化 UART 的底層資源
配置 UART 引腳
若是使用了中斷須要配合 NVIC 中斷優先級
若是使用了DMA處理須要配置DMA
HAL_UART_Init()
異步通訊 HAL_HalfDuplex_Init()
半雙工通訊HAL_LIN_Init()
LIN總線通訊HAL_MultiProcessor_Init()
多處理器通訊HAL_StatusTypeDef HAL_UART_Init (UART_HandleTypeDef * huart)
HAL_StatusTypeDef HAL_HalfDuplex_Init (UART_HandleTypeDef * huart)
HAL_StatusTypeDef HAL_LIN_Init (UART_HandleTypeDef * huart, uint32_t BreakDetectLength)
HAL_StatusTypeDef HAL_MultiProcessor_Init (UART_HandleTypeDef * huart, uint8_t Address, uint32_t WakeUpMethod)
HAL_StatusTypeDef HAL_UART_DeInit (UART_HandleTypeDef * huart)
參數說明:
*huart
UART句柄結構體的指針void HAL_UART_MspInit (UART_HandleTypeDef * huart)
void HAL_UART_MspDeInit (UART_HandleTypeDef * huart)
HAL_StatusTypeDef HAL_UART_Transmit (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Receive (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size, uint32_t Timeout)
參數說明:
*huart
: UART句柄,用於操做UART*pData
: 緩衝區指針Size
: 緩衝區大小(以字節爲單位)Timeout
: 超時時間,不可能讓程序一直等待數據接收或發送,超過這個時間以後將放棄發送或接收HAL_StatusTypeDef HAL_UART_Transmit_IT (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
HAL_StatusTypeDef HAL_UART_Receive_IT (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
參數說明:
*huart
: UART句柄,用於操做UART*pData
: 緩衝區指針Size
: 緩衝區大小(以字節爲單位)以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; } }
void HAL_UART_IRQHandler (UART_HandleTypeDef * huart)
void USARTx_IRQHandler()
中調用該函數,或者能夠由STM32CubeMX
程序自動生成。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通訊的流程
HAL_UART_Init()
初始化UART(該函數會調用HAL_UART_MspInit()
來初始化底層服務)HAL_UART_Receive/Transmit_IT()
準備開始接收或者發送數據USARTx_IRQHandler()
HAL_UART_IRQHandler()
UART_Receive_IT()
UART_Transmit_IT()
UART_EndTransmit_IT()
三個函數中的一個,當發送/接收完成後調用相應的回調函數(根據HAL_UART_Receive/Transmit_IT()
的size參數來判斷是否完成發送/接收)如要提升程序執行的效率能夠重寫USARTx的中斷服務函數,無需調用UART中斷的公共接口而自行更具相應的標識來處理接收或發送的流程。
HAL_StatusTypeDef HAL_UART_Transmit_DMA (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
HAL_StatusTypeDef HAL_UART_Receive_DMA (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size)
6HAL_UART_StateTypeDef HAL_UART_GetState (UART_HandleTypeDef * huart)
uint32_t HAL_UART_GetError (UART_HandleTypeDef * huart)
具體參見stm32f4xx_hal.h
頭文件