USART_GetFlagStatus函数与USART标志位详解

/*****************  发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
	/* 发送一个字节数据到USART */
	USART_SendData(pUSARTx,ch);
		
	/* 等待发送数据寄存器为空 */
	while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);	
}

这个函数Usart_SendByte本身并不是STM32标准外设库(HAL库或旧的标准外设库)中直接提供的函数,但它遵循了STM32 USART(通用同步异步收发传输器)通信的一种常见实现模式。这个函数看起来像是用户为了简化USART数据发送过程而自定义的封装函数。

解析这个函数:

  1. 函数定义
  2. void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch):这个函数接收两个参数,一个是指向USART_TypeDef结构体的指针pUSARTx,这个结构体是STM32库中定义的,用于表示USART的寄存器地址和位定义;另一个是uint8_t类型的ch,即要发送的字节数据。
  3. 发送数据
  4. USART_SendData(pUSARTx,ch);:这行代码调用了STM32库中的一个函数(可能是在标准外设库或HAL库中),用于将单个字节ch写入到指定的USART(通过pUSARTx指定)的发送数据寄存器(TDR)中。这个函数实际上启动了数据的发送过程。
  5. 等待发送完成
  6. while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);:这行代码是一个忙等待循环,它检查USART的发送数据寄存器空标志(TXE)。当TXE标志被设置(即发送数据寄存器为空)时,表示上一个字节已经被发送出去,USART准备好发送下一个字节。在USART_FLAG_TXERESET(即未设置)时,循环继续执行,直到TXE标志被设置,此时循环结束,函数返回。这种方式确保了发送函数在数据真正发送出去之前不会返回。

总结

  • 这个函数Usart_SendByte是用户自定义的,它封装了USART发送单个字节数据的过程,包括写入数据和等待发送完成。
  • 它使用了STM32库中的函数(如USART_SendDataUSART_GetFlagStatus)来实现其功能,但提供了更简洁的接口给调用者。
  • 自定义这样的函数是嵌入式编程中常见的做法,旨在提高代码的可读性和复用性。
  • /**
      * @brief  Checks whether the specified USART flag is set or not.
      * @param  USARTx: Select the USART or the UART peripheral. 
      *   This parameter can be one of the following values:
      *   USART1, USART2, USART3, UART4 or UART5.
      * @param  USART_FLAG: specifies the flag to check.
      *   This parameter can be one of the following values:
      *     @arg USART_FLAG_CTS:  CTS Change flag (not available for UART4 and UART5)
      *     @arg USART_FLAG_LBD:  LIN Break detection flag
      *     @arg USART_FLAG_TXE:  Transmit data register empty flag
      *     @arg USART_FLAG_TC:   Transmission Complete flag
      *     @arg USART_FLAG_RXNE: Receive data register not empty flag
      *     @arg USART_FLAG_IDLE: Idle Line detection flag
      *     @arg USART_FLAG_ORE:  OverRun Error flag
      *     @arg USART_FLAG_NE:   Noise Error flag
      *     @arg USART_FLAG_FE:   Framing Error flag
      *     @arg USART_FLAG_PE:   Parity Error flag
      * @retval The new state of USART_FLAG (SET or RESET).
      */
    FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)
    {
      FlagStatus bitstatus = RESET;
      /* Check the parameters */
      assert_param(IS_USART_ALL_PERIPH(USARTx));
      assert_param(IS_USART_FLAG(USART_FLAG));
      /* The CTS flag is not available for UART4 and UART5 */
      if (USART_FLAG == USART_FLAG_CTS)
      {
        assert_param(IS_USART_123_PERIPH(USARTx));
      }  
      
      if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET)
      {
        bitstatus = SET;
      }
      else
      {
        bitstatus = RESET;
      }
      return bitstatus;
    }
    

    这个函数 USART_GetFlagStatus 是用于检查STM32 USART(或UART)外设中特定标志位的状态的。这个函数返回一个 FlagStatus 枚举类型的值,通常是 SETRESET,分别表示标志位被设置或未被设置。下面是对这个函数的详细理解:

    函数参数

  • USART_TypeDef* USARTx:这是一个指向USART(或UART)外设寄存器的指针。STM32的库定义了多个USART(或UART)外设的寄存器映射到USART_TypeDef结构体中,这个指针用于指定要检查哪个USART外设的标志位。
  • uint16_t USART_FLAG:这是要检查的USART标志位的标识符。STM32的USART外设具有多个状态标志位和错误标志位,这个参数指定了要查询的具体哪个标志位。
  • 函数内部逻辑

    1. 参数检查
    2. 使用assert_param宏来检查传入的USARTxUSART_FLAG参数是否有效。这是为了确保传递给函数的参数是USART外设的有效实例和USART标志位的有效标识符。如果参数无效,assert_param可能会导致程序中断(具体行为取决于编译器的设置)。
    3. 特别地,对于USART_FLAG_CTS(清除发送)标志,该函数还检查指定的USART外设是否支持该标志(因为不是所有的USART外设都支持CTS标志,比如UART4和UART5)。
    4. 读取标志位状态
    5. 通过检查USARTx->SR寄存器和传入的USART_FLAG标志位进行位与操作,来判断该标志位是否被设置。USARTx->SR是USART状态寄存器的指针,包含了USART的各种状态信息。
    6. 如果位与操作的结果不为0(即(USARTx->SR & USART_FLAG) != (uint16_t)RESET),则表示该标志位被设置,bitstatus被设置为SET
    7. 否则,bitstatus保持为RESET,表示该标志位未被设置。
    8. 返回标志位状态
    9. 函数最后返回bitstatus的值,即所查询的标志位的状态。

    注意事项

  • FlagStatus是一个枚举类型,通常定义在STM32的库头文件中,用于表示标志位的状态。它通常包含SETRESET两个值。
  • 这个函数是阻塞的,即它会立即返回标志位的状态,而不会等待任何条件的变化。
  • 在实际使用中,需要注意STM32的USART标志位可能会因不同的中断事件而被自动清除,因此在某些情况下,可能需要先禁用相关的中断或使用其他机制来避免错过标志位的状态变化。
  • USART_FLAG_CTS标志位的检查是特定于硬件的,因为不是所有的STM32 USART外设都支持CTS功能。对于不支持CTS的USART外设,查询该标志位可能会导致错误的行为或断言失败。
  •         在STM32的编程中,USARTx->SR 这种写法是访问STM32微控制器中USART(或UART)外设的状态寄存器(Status Register,简称SR)的一种方式。这里,USARTx 是一个指向USART(或UART)外设寄存器组的指针,而 -> 是C语言中的结构体指针成员访问运算符,用于访问结构体指针所指向的结构体中的成员。SR 是USART状态寄存器的一个成员,用于存储USART的各种状态信息,如发送缓冲区空(TXE)、接收缓冲区非空(RXNE)、传输完成(TC)等标志位。

    具体来说,USARTx->SR 的工作流程如下:

    1. USARTx 指针USARTx 是一个指向特定USART(或UART)外设寄存器组的指针。在STM32的库函数中,这个指针通常是通过宏定义或枚举来指定的,比如 USART1USART2USART3 等,它们分别对应不同的USART外设。

    2. 结构体指针成员访问-> 运算符用于通过结构体指针访问结构体的成员。在这个上下文中,它被用来访问 USARTx 指向的USART结构体中的 SR 成员。

    3. 状态寄存器(SR)SR 是一个包含多个状态标志位的寄存器。每个标志位都代表了一个特定的状态或条件,比如数据发送完成、接收缓冲区中有数据等。

    4. 检查SR:要检查SR寄存器中的特定标志位,你可以使用位操作。例如,如果你想检查发送缓冲区是否为空(TXE标志位),你可以这样做:

      if ((USARTx->SR & USART_SR_TXE) != 0) {
      // 发送缓冲区为空,可以发送新数据
      }

      在这里,USART_SR_TXE 是一个宏定义,它表示TXE标志位在SR寄存器中的位置(即它的位掩码)。通过与操作(&),你可以检查TXE标志位是否被设置(即是否为1)。

    5. 位掩码USART_SR_TXE 等宏定义实际上是位掩码,它们只在一个特定的位上设置为1,其余位都设置为0。这样,当你将这个掩码与SR寄存器的值进行与操作时,结果将只包含你感兴趣的标志位的状态。

    6. 注意:在STM32的某些库版本中,可能直接使用标志位的名称(如 USART_FLAG_TXE)而不是寄存器名称加位掩码(如 USART_SR_TXE)来检查标志位。但是,原理是相同的,只是宏定义的命名约定可能有所不同。

    总结来说,USARTx->SR 是一种通过结构体指针访问STM32 USART外设状态寄存器的方式,而检查SR寄存器中的特定标志位则涉及到位操作和对相应宏定义的使用。

    注:

    #define USART_FLAG_CTS                       ((uint16_t)0x0200)
    #define USART_FLAG_LBD                       ((uint16_t)0x0100)
    #define USART_FLAG_TXE                       ((uint16_t)0x0080)
    #define USART_FLAG_TC                        ((uint16_t)0x0040)
    #define USART_FLAG_RXNE                      ((uint16_t)0x0020)
    #define USART_FLAG_IDLE                      ((uint16_t)0x0010)
    #define USART_FLAG_ORE                       ((uint16_t)0x0008)
    #define USART_FLAG_NE                        ((uint16_t)0x0004)
    #define USART_FLAG_FE                        ((uint16_t)0x0002)
    #define USART_FLAG_PE                        ((uint16_t)0x0001)

    作者:且听牛哞

    物联沃分享整理
    物联沃-IOTWORD物联网 » USART_GetFlagStatus函数与USART标志位详解

    发表回复