USART_ClearITPendingBith和 USART_ClearFlag的区别

stm32 v3.5 库函数里面,对于串口USART有这样两个函数:
USART_ClearFlag()和USART_ClearITPendingBit()

查库函数定义,说一个是清除标志,一个是清除中断预处理位。
然后我看了stm32f10x_usart.c文件,发现两个函数都操作的是USART->SR寄存器,
但是这个寄存器只有一组标志位,没有什么中断预处理位。。

实际上两个函数实现的功能是一样的,都是清除相对应的标志位,只是标志位和中断位含义不一样,是标志位但是不一定会产生中断。例如:

#define ADC_IT_EOC                                 ((uint16_t)0x0220)
#define ADC_IT_AWD                                 ((uint16_t)0x0140)
#define ADC_IT_JEOC                                ((uint16_t)0x0480)
这是中断位,可以产生中断

#define ADC_FLAG_AWD                               ((uint8_t)0x01)
#define ADC_FLAG_EOC                               ((uint8_t)0x02)
#define ADC_FLAG_JEOC                              ((uint8_t)0x04)
#define ADC_FLAG_JSTRT                             ((uint8_t)0x08)
#define ADC_FLAG_STRT                              ((uint8_t)0x10)
这是标志位,有的标志位不能产生中断
标志位在程序中可以作为判定条件,支持程序的运行,中断则是跳转到中断函数执行。两个函数实现的功能是一样的,在中断程序中可以用两个中的任一个。我想区分两个函数是为了更清晰吧。
还有

#define ADC_IT_EOC                                 ((uint16_t)0x0220)
#define ADC_FLAG_EOC                             ((uint8_t)0x02)

这两个数值不同是因为标志位只是为了清除标志位而设的,而中断位设置成这个值是因为在其他函数中这一位还有其他用途。而且还要注意:
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)

{
  assert_param(IS_ADC_ALL_PERIPH(ADCx));
  assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG));
  ADCx->SR = ~(uint32_t)ADC_FLAG;
}

 这一步 ADCx->SR = ~(uint32_t)ADC_FLAG;似乎应该是  ADCx->SR &= ~(uint32_t)ADC_FLAG;
其实状态位只能有硬件置位,软件只能读和清零,所以这样写也是正确的。
没有很明白,所以转在这里,等我哪天灵光乍现了,再来加上我的理解

                --------------------------------------------------------------------------------------------------------

我是在使用TC的时候遇见这个问题的,所以这里就只分析TC这个位

先研究简单点的USART_ClearFlag函数

//调用形式
USART_ClearFlag(USART3,USART_FLAG_TC);

//USART_FLAG_TC的定义
#define USART_FLAG_TC               ((uint16_t)0x0040)

//USART_ClearFlag函数的原型
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
  assert_param(IS_USART_PERIPH_FLAG(USARTx, USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */   
   
  USARTx->SR = (uint16_t)~USART_FLAG;
}

一目了然,最后USARTx->SR = ~(0100'0000);

再来研究复杂点的USART_ClearITPendingBit函数(注意,这两个函数的第二个参数,是不一样的)

//调用形式
USART_ClearITPendingBit(USART3,USART_IT_TC);

//USART_IT_TC的定义
#define USART_IT_TC           ((uint16_t)0x0626)//=0000'0110'0010'0110

//USART_ClearITPendingBit的函数原型
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)
{
  uint16_t bitpos = 0x00, itmask = 0x00;
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_CLEAR_IT(USART_IT));
  assert_param(IS_USART_PERIPH_IT(USARTx, USART_IT)); /* The CTS interrupt is not available for UART4 and UART5 */
  
  bitpos = USART_IT >> 0x08;                     //=0000'0110
  itmask = (uint16_t)((uint16_t)0x01 << bitpos); //=0100'0000
  USARTx->SR = (uint16_t)~itmask;                //=~(0100'0000)
}

可以看到最后还是USARTx->SR=~(0100'0000);

对比一下USART_ClearFlag和USART_ClearITPendingBit的参数

USART_ClearFlag的参数 USART_ClearITPendingBit的参数
USART_FLAG_CTS    = 0x0200 USART_IT_CTS  = 0x096A
USART_FLAG_LBD    = 0x0100 USART_IT_LBD   = 0x0846
USART_FLAG_TC      = 0x0040 USART_IT_TC     = 0x0626
USART_FLAG_RXNE = 0x0020 USART_IT_RXNE = 0x0525
这里可以发现一个规律USART_ClearFlag参数只有一个位是“1”,其位置正 等于USART_ClearITPendingBit的参数左移八位后的结果,所以这里可以非常非常肯定的讲函数USART_ClearFlag和函数USART_ClearITPendingBit的功能totally一样

----------------------------------------------------------------------------------------------------------------------------

涉及内容扩展:

STM32的USART发送数据时如何使用TXE和TC标志

     在USART的发送端有2个寄存器,一个是程序可以看到的寄存器——发送数据寄存器(通过USART_DR查看,另一个是程序看不到的寄存器——发送移位寄存器,对应的两个USART数据发送标志,一个是TXE=发送数据寄存器空,另一个是TC=发送移位寄存器空


(这粗箭头和这细箭头,简直不要太形象哦,粗箭头是八位八位的传,细箭头是一位一位的传)

    当USART_DR中的数据传送到移位寄存器后,TXE被设置,此时移位寄存器开始向TX信号线按位传输数据,但因为TDR已经变空,所以程序可以把下一个要发送的字节(操作USART_DR)写入TDR中,而不必等到移位寄存器中所有位发送结束,所有位发送结束时(送出停止位后)硬件会设置TC标志

  另一方面,在刚刚初始化好USART还没有发送任何数据时,也会有TXE标志,因为这时发送数据寄存器是空的。TXEIE和TCIE的意义很简单,TXEIE允许在TXE标志为'1'时产生中断,而TCIE允许在TC标志为'1'时产生中断。

  至于什么时候使用哪个标志,需要根据你的需要自己决定。但我认为TXE允许程序有更充裕的时间填写TDR寄存器,保证发送的数据流不间断。TC可以让程序知道发送结束的确切时间,有利于程序控制外部数据流的时序。

7

TXE:发送数据寄存器空 (Transmit data register empty)

TDR寄存器中的数据被硬件转移到移位寄存器的时候,该位被硬件置位。如果USART_CR1寄存器中的TXEIE1,则产生中断。对USART_DR的写操作,将该位清零。

0:数据还没有被转移到移位寄存器;
1:数据已经被转移到移位寄存器。
注意:单缓冲器传输中使用该位。
位6

TC:发送完成 (Transmission complete)

当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将该位置’1’。如果USART_CR1中的TCIE’1’,则产生中断。由软件序列清除该位(先读USART_SR,然后写入USART_DR)TC位也可以通过写入’0’来清除,只有在多缓存通讯中才推荐这种清除程序。

0:发送还未完成;
1:发送完成
位5 RXNE:读数据寄存器非空 (Read data register not empty)
RDR移位寄存器中的数据被转移到USART_DR寄存器中,该位被硬件置位。如果USART_CR1寄存器中的RXNEIE1,则产生中断。对USART_DR的读操作可以将该位清零。 RXNE位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。
0:数据没有收到;
1:收到数据,可以读出。
这下算是功德圆满了吧

猜你喜欢

转载自blog.csdn.net/qq_35629563/article/details/80879819