STM32 uart发送数据,查询 USART_FLAG_TC 正常。但使用 USART_FLAG_TXE 会乱码。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32 uart发送数据,查询 USART_FLAG_TC 正常。但使用 USART_FLAG_TXE 会乱码。相关的知识,希望对你有一定的参考价值。

在一个发送单字节的函数中我用下面写法可以正常工作
USART1->DR = ch & 0xff;
while (!(USART1->SR & USART_FLAG_TC));
但是如果第二句写成
while (!(USART1->SR & 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操作,这样是不是就可以节省很多时间了?

至于出现乱码,你需要综合其他的代码来进行分析。

追问

谢谢你这么详细的解答。我这个循环等待的语句就是依照参考手册写的。全程序只有这一处改动了,就会出现乱码。
我也实在想不到其它哪里会影响TXE的使用。关于排查,能提供我一些思路吗?

追答

不知道你程序的作用,也没有看到其他代码的情况下,我能想到的也就只有点:
1、和接收发送冲突,情况可能会是这样的:“发送移位寄存器”中的内容正在被发送到TX,且USARTx->DR中也有等待被发送的数据,这时候有数据接收过来,新接收的数据也是需要存放在USARTx->DR里面的,这样也许会导致不可预知的错误发生。
2、在你发送的最后一个字节上,假设你发送完最后一个字节后就关闭了串口或者关闭发送功能等等,那就会发生错误或乱码,因为:
在while (!(USART1->SR & USART_FLAG_TXE));之后表示数据已经转移到“发送移位寄存器”中,此时要发送的是最后一个字节,这时你认为数据已经完全发送,但实际上此时数据并没有真正意义上的完全发送,还需要等待“发送移位寄存器”中的数据发送出去才算是完全发送,而也就在这时你关闭了串口,那么最后这个字节的发送是失败的,会产生错误或乱码。

参考技术A 需要帮你写程序吗

STM32 MX Cube生成的工程中 使用printf向Uart发送数据

1. 在main函数前面添加:

int fputc(int ch,FILE *f)
{
uint8_t temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,2);
return(ch);
}

 

2. USE Micro Lib

以上是关于STM32 uart发送数据,查询 USART_FLAG_TC 正常。但使用 USART_FLAG_TXE 会乱码。的主要内容,如果未能解决你的问题,请参考以下文章

如何在stm32的hal库uart发送函数怎么用

STM32F4 UART1 DMA发送和接收不定长度数据

STM32串口发送接收数据

STM32 MX Cube生成的工程中 使用printf向Uart发送数据

基于STM32之UART串口通信协议发送

stm32f412 SPI dma接收和UART dma发送问题解决