STM32用USART发送字符串,以USART_FLAG_TXE和USART_FLAG_TC怎么用

  • Post author:
  • Post category:其他


一:STM32用USART发送字符串

void UART_Send_Message(u8 *Data)
{
  while(*Data!='\0')
  {
      USART_SendData(USART1, *Data);
      while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);//读取串口状态
      Data++;
  }
}
 
void main(void)
{
	u8 str_buf[500];
	memset((char *) &str_buf, 0, sizeof(str_buf));
	UART_Send_Message(str_buf);
}

while(SET == USART_GetFlagStatus(USART1,USART_FLAG_RXNE));

含义是:当接收引脚有数据时,状态寄存器的USART_FLAG_RXNE就会为1,此时USART_GetFlagStatus(USART1,USART_FLAG_RXNE)的返回值就为1(SET),若无数据则为RESET。

二:USART_FLAG_TXE和USART_FLAG_TC怎么用

这里主要说的是在特殊情况下发送字符软件代码的写法。

特殊情况指的是:

1.调用发送字符串函数“发送完”

本机

立即掉电;

2.调用发送字符串函数“发送完”

从机

立即掉电;

【上面两种主要用于芯片对电源控制的项目中】

3.调用发送字符串函数“发送完”立刻进入待机或停机;

其实本文主要说的是两个标志位:USART_FLAG_TXE 和 USART_FLAG_TC.


USART_FLAG_TXE

发送缓冲区空标志:说明可以往数据寄存器写入数据了,但并不代码数据发送完成了。


USART_FLAG_TC

发送完成标志:这个才是代表USART在缓冲区的数据发送完成了,即从机接收到了数据。

这两个标志的区别在于:它们分别表示数据在发送过程中,在两个不同的阶段中的完成情况。TXE 表示数据被从发送缓冲区中取走,转移到的移位寄存器中,此时发送缓冲是空的,可以向其中补充新的数据了。而 TC 则表示最后放入发送缓冲区的数据已经完成了从移位寄存器向发送信号线 Tx 上的转移。所以,判定数据最终发送完成的标志是 TC,而不是 TXE.

下面讲述在不同代码写法下,得到不同实验效果【调试助手接收数据】:

这种写法在不是特殊(不掉电、不待机等)情况下,问题不大,USART数据会成功发送出去。 但是在上面说的特殊情况下,问题就来了,代码只将数据放到了发送缓冲区,而没有发送出去就掉电或待机了,这个时候其实最后两个字符是没有发送出去的。

这种写法达到的效果和上面存在不同的就是倒数第二个数据发送出去了,也就是只有最后一个字符是没有发送出去的。

这种写法达到的效果和上面两种写法有不一样,发送了10个字符。

这种写法按理说可以实现功能,但实际多次试验结果确实第一字节数据丢失了。

写法4丢失第一个字节是因为,在发送第一个字节之前没有将TC状态位置0,跳过了第一个字节后的while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);,导致第二个字节的数据覆盖了第一个字节的数据。至于为什么没有将TC置0,STM32F10x手册相关部分写着,清除TC需要:1.读SR寄存器2.写DR寄存器。第一个字节的时候只写了DR,没有读SR。如果在第一个字节前加USART_ClearFlag(USARTx, uint16_t USART_FLAG_TC);,可以解决问题

这种写法是比较完成,为了保守起见,在特殊情况下使用该写法。



先说串口收发过程:

对于CPU来说,只需要将数据填入发送数据寄存器中就可以启动串口发送了,因为数据寄存器中的数据会由硬件自动打入发送移位寄存器中;同理,接收移位寄存器中一旦接收到一字节的数据后,移位寄存器中的数据会被硬件自动打入接收数据寄存器中,CPU就可以从接收数据寄存器中取数据了。也就是如下图所示的原理:



USART_FLAG_TC是干嘛用的呢?

当发送移位寄存器中的1字节数据已经通过TX脚一位一位的移出去后,该标志位就会被置1,从而引发该事件的中断。所以,其实USART_FLAG_TC就是用来标志“发送移位寄存器中的数据有没有全部发送出去”这件事的。



USART_FLAG_TXE是干嘛用的呢?

当发送数据寄存器中的数据已经取完了,该标志位就会被置1,从而引发该事件的中断。所以,其实USART_FLAG_TXE就是用来标志一个事件的,通过它的值可以知道该事件有没有发生(即发送数据寄存器中的数据有没有被取走)。



两者分别在何种情况下被应用?

1、有不少刚入门的开发人员总是认为USART_FLAG_TC 与 USART_FLAG_TXE所代表的意义似乎没有区别,两者没有必要都存在。甚至有人认为这两个标志位都为1的时候都代表数据已经发送完成了。这肯定是错误的,那么多单片机厂家不可能犯同一个错误,而且芯片设计都是些顶尖的专家,更不可能犯这种简单的逻辑错误。

2、那么该如何看待这两个标志位的应用场景呢?其实仔细看我上面关于这两个标志位的说明就可以找到答案。显然,对于USART_FLAG_TXE来说,只是说明数据寄存器中的数据已经被发送移位寄存器取走了(但发送移位寄存器中可能还没有启动发送过程),通过中断就可以提醒CPU可以往数据寄存器中填充数据了,发送移位寄存器中的数据往外发送的过程其实还是比较耗时的,相对于C语言代码执行时间来说,这个过程的耗时完全算得上是一个宏观的数据,所以每次发送数据寄存器中的数据被发送移位寄存器取走后,都应该产生中断来提醒CPU对该寄存器更新数据;而对于USART_FLAG_TC来说,没必要每次当发送移位寄存器中的数据发送完成后都发生中断,而应该是整个串口数据帧全部发送完毕,包括最后一个字节也发送出去之后才应该开中断,这代表的就是一个数据帧发送完成事件了。

参考:1、

https://blog.csdn.net/weibo1230123/article/details/80382150

2、

https://blog.csdn.net/tanguohua_666/article/details/90770693