本文绝大部分翻译自ST的官方用户手册 Description of STM32F4 HAL and LL driversapi
USART 与 UART 的区别在于有没有同步通讯的功能。
USART: 通用同步异步收发器 ; UART: 通用异步收发器。缓存当进行异步通讯时,这二者是没有区别的。
这个同步通讯功能能够把USART当作SPI来用,好比用USART来驱动SPI设备。异步同步(阻塞模式)是指:发送方发出数据后,等接收方发回响应之后才发下一个数据包的通信方式。
异步(非阻塞模式)是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通信方式。ide其中SPI IIC为同步通讯 UART为异步通讯, usart为同步&异步通讯。函数
参考:https://blog.csdn.net/anbaixiu/article/details/78635913ui
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 容许发送数据code
参见: UART通讯中流控RTS和CTS的理解 https://blog.csdn.net/u013797023/article/details/77935535
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
该结构体定义的则是UART句柄(我的理解为用于操做UART)的一些参数
该结构体中只有*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__)
所实现的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)
UART_HandleTyperDef
句柄结构体HAL_UART_MspInit()
初始化 UART 的底层资源
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)
UART上层参数的初始化/注销函数,根据工做模式选用相应的初始化函数
须要配置的参数包括 波特率、字长、中止位、奇偶校验模式、是否开启硬件流控制、收发模式、过采样模式
参数说明:
*huart
UART句柄结构体的指针返回API的执行状况,调用时注意检查
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
: 超时时间,不可能让程序一直等待数据接收或发送,超过这个时间以后将放弃发送或接收返回该API的执行状态
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)
用于开启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; } }
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
头文件