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数据发送过程而自定义的封装函数。
解析这个函数:
- 函数定义:
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
:这个函数接收两个参数,一个是指向USART_TypeDef
结构体的指针pUSARTx
,这个结构体是STM32库中定义的,用于表示USART的寄存器地址和位定义;另一个是uint8_t
类型的ch
,即要发送的字节数据。- 发送数据:
USART_SendData(pUSARTx,ch);
:这行代码调用了STM32库中的一个函数(可能是在标准外设库或HAL库中),用于将单个字节ch
写入到指定的USART(通过pUSARTx
指定)的发送数据寄存器(TDR)中。这个函数实际上启动了数据的发送过程。- 等待发送完成:
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
:这行代码是一个忙等待循环,它检查USART的发送数据寄存器空标志(TXE)。当TXE标志被设置(即发送数据寄存器为空)时,表示上一个字节已经被发送出去,USART准备好发送下一个字节。在USART_FLAG_TXE
为RESET
(即未设置)时,循环继续执行,直到TXE标志被设置,此时循环结束,函数返回。这种方式确保了发送函数在数据真正发送出去之前不会返回。
总结:
Usart_SendByte
是用户自定义的,它封装了USART发送单个字节数据的过程,包括写入数据和等待发送完成。USART_SendData
和USART_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
枚举类型的值,通常是 SET
或 RESET
,分别表示标志位被设置或未被设置。下面是对这个函数的详细理解:
函数参数
USART_TypeDef* USARTx
:这是一个指向USART(或UART)外设寄存器的指针。STM32的库定义了多个USART(或UART)外设的寄存器映射到USART_TypeDef
结构体中,这个指针用于指定要检查哪个USART外设的标志位。uint16_t USART_FLAG
:这是要检查的USART标志位的标识符。STM32的USART外设具有多个状态标志位和错误标志位,这个参数指定了要查询的具体哪个标志位。函数内部逻辑
- 参数检查:
- 使用
assert_param
宏来检查传入的USARTx
和USART_FLAG
参数是否有效。这是为了确保传递给函数的参数是USART外设的有效实例和USART标志位的有效标识符。如果参数无效,assert_param
可能会导致程序中断(具体行为取决于编译器的设置)。 - 特别地,对于
USART_FLAG_CTS
(清除发送)标志,该函数还检查指定的USART外设是否支持该标志(因为不是所有的USART外设都支持CTS标志,比如UART4和UART5)。 - 读取标志位状态:
- 通过检查
USARTx->SR
寄存器和传入的USART_FLAG
标志位进行位与操作,来判断该标志位是否被设置。USARTx->SR
是USART状态寄存器的指针,包含了USART的各种状态信息。 - 如果位与操作的结果不为0(即
(USARTx->SR & USART_FLAG) != (uint16_t)RESET
),则表示该标志位被设置,bitstatus
被设置为SET
。 - 否则,
bitstatus
保持为RESET
,表示该标志位未被设置。 - 返回标志位状态:
- 函数最后返回
bitstatus
的值,即所查询的标志位的状态。
注意事项
FlagStatus
是一个枚举类型,通常定义在STM32的库头文件中,用于表示标志位的状态。它通常包含SET
和RESET
两个值。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
的工作流程如下:
-
USARTx 指针:
USARTx
是一个指向特定USART(或UART)外设寄存器组的指针。在STM32的库函数中,这个指针通常是通过宏定义或枚举来指定的,比如USART1
、USART2
、USART3
等,它们分别对应不同的USART外设。 -
结构体指针成员访问:
->
运算符用于通过结构体指针访问结构体的成员。在这个上下文中,它被用来访问USARTx
指向的USART结构体中的SR
成员。 -
状态寄存器(SR):
SR
是一个包含多个状态标志位的寄存器。每个标志位都代表了一个特定的状态或条件,比如数据发送完成、接收缓冲区中有数据等。 -
检查SR:要检查SR寄存器中的特定标志位,你可以使用位操作。例如,如果你想检查发送缓冲区是否为空(TXE标志位),你可以这样做:
if ((USARTx->SR & USART_SR_TXE) != 0) {
// 发送缓冲区为空,可以发送新数据
}
在这里,
USART_SR_TXE
是一个宏定义,它表示TXE标志位在SR寄存器中的位置(即它的位掩码)。通过与操作(&
),你可以检查TXE标志位是否被设置(即是否为1)。 -
位掩码:
USART_SR_TXE
等宏定义实际上是位掩码,它们只在一个特定的位上设置为1,其余位都设置为0。这样,当你将这个掩码与SR寄存器的值进行与操作时,结果将只包含你感兴趣的标志位的状态。 -
注意:在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)
作者:且听牛哞