STM32 串口通信中 USART_FLAG_TC 与 USART_FLAG_TXE 区别(摘自网络)
首先了解STM32串口发送数据的简单过程,如下图所示。
发送:软件将数据写到USARTx->DR里面,硬件自动把USARTx->DR里面的数据并行转移到“发送一位知寄存器”,然后硬件自动将发送一位寄存器中的数据通过TX引脚串行发送出去。接收:RX上有数据过来,则先将数据一位一位的放到“接收移位寄存器”里面,收满一个字节后,硬件自动将“接收移位寄存器”里面的数据并行转移到USARTx->DR里面。
while (!(USART1->SR & USART_FLAG_TC));这句是等待数据完完全全从“发送移位寄存器”中发送出去,while (!(USART1->SR & USART_FLAG_TXE));这句是等待数据从USARTx->DR转移到“发送移位寄存器”中。在后一句的写道法中,并不需等待数据完全发送,只需要USARTx->DR里面的数据已经被转移走,就可以马上进行再次写入USARTx->DR操作,这样是不是就可以节省很多时间了?至于出现乱码,你需要综合其他的代码来进行分析。
举例:STM32 uart发送数据,查询 USART_FLAG_TC 正常,但使用 USART_FLAG_TXE 会乱码。
在一个发送单字节的函数中我用下面写法可以正常工作
USART1->DR = ch & 0xff;
while (!(USART1->SR & USART_FLAG_TC));
但是如果第二句写成
while (!(USART1->SR & USART_FLAG_TXE));
就会在连续调用这个函数时输出乱码(一般第一个字符是正确的)。
分析问题:收发冲突
1、和接收发送冲突,情况可能会是这样的:“发送移位寄存器”中的内容正在被发送到TX,且USARTx->DR中也有等待被发送的数据,这时候有数据接收过来,新接收的数据也是需要存放在USARTx->DR里面的,这样也许会导致不可预知的错误发生。
2、在你发送的最后一个字节上,假设你发送完最后一个字节后就关闭了串口或者关闭发送功能等等,那就会发生错误或乱码,因为:
在while (!(USART1->SR & USART_FLAG_TXE));之后表示数据已经转移到“发送移位寄存器”中,此时要发送的是最后一个字节,这时你认为数据已经完全发送,但实际上此时数据并没有真正意义上的完全发送,还需要等待“发送移位寄存器”中的数据发送出去才算是完全发送,而也就在这时你关闭了串口,那么最后这个字节的发送是失败的,会产生错误或乱码。