STM32F4 HAL库 UART相干API介绍

本文绝大部分翻译自ST的官网用户手册 Description of STM32F4 HAL and LL drivers

USART 与 UART 的区别在于有没有同步通信的性能。
USART: 通用同步异步收发器 ; UART: 通用异步收发器。

当进行异步通信时,这两者是没有区别的。
这个同步通信性能能够把USART当做SPI来用,比方用USART来驱动SPI设施。

同步(阻塞模式)是指:发送方收回数据后,等接管方发回响应当前才发下一个数据包的通信形式。
异步(非阻塞模式)是指:发送方收回数据后,不等接管方发回响应,接着发送下个数据包的通信形式。

其中SPI IIC为同步通信 UART为异步通信, usart为同步&异步通信。

参考:https://blog.csdn.net/anbaixi...

硬件相干常识

STM32F427/STM32F429 共有4个USART与4个UART,如下表

序号U(S)ART_RX引脚U(S)ART_TX引脚U(S)ART_CK引脚USART_ CTS引脚USART_ RTS引脚
USART1PA10PA9PA8PA11PA12
USART2PA3/PD6PA2/PD5PA4/PD7PA0/PD3PA1/PD4
USART3PB11/PC11/PD9PB10/PC10/PD8PB12/PC12/PD10PB13/PD11PB14/PD12
UART4PA1/PC11PA0/PC10
UART5PD2PC12
USART6PC7/PG9PC6/PG14PC8/PG7PG13/PG15PG8/PG12
UART7PE7PE8
UART8PE0PE1
RT: Receive Data 接收数据
TX: Transmit Data 发送数据
CK: Clock (同步)时钟

硬件流控制

RTS: Request To Send 申请发送数据
CTS: Clear To Send 容许发送数据

参见: UART通信中流控RTS和CTS的了解 https://blog.csdn.net/u013797...

相干构造体变量

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__)所实现的

    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头文件