本帖最后由 香水城 于 2017-8-17 14:23 编辑
UART 发送数据丢失最后一个字节
问题:
该问题由某客户提出,发生在 STM32F103VCT6 器件上。据其工程师讲述:在其产品的设计中要使用 STM32 的 STOP 低功耗模式。而在使 STM32 进入 STOP 模式之前,需要对整个系统做一些设置工作, 其中一项工作是通过 USART3 向某个功能模组发送一个命令报文。在实测中发现,该报文没有发全, 总是缺少最后一个字节。
调研:
使用示波器观察 STM32 在进入 STOP 模式前从 USART3 发出的最后一个报文,确认的确缺 少正常报文的最后一个字节。编写测试程序,每一秒钟从 USART3 发送一次该报文。借助 windows 的超级终端接收,经长时间观察,未见异常。修改其软件,将进入 STOP 模 式的代码用 while(1)替代,如表(一)所示:
重新编译、执行。使用示波器观察,程序在执行到 while(1)之前,STM32 从 USART3 发 出的最后一个报文。结果显示,该报文是完整的,如图(一)所示:
修改代码,在 while(1)语句之前加一行对 GPIO 翻转的代码,如表(二)所示:
重新编译、执行。使用示波器观察,STM32 从 USART3 发出的最后一个报文与 PB7 上的信号的相位关 系。结果表明,报文的最后一个字节发出之前,PB7 已翻转,如图(二)所示:
由此可以推断:运行原来的程序时,STM32 在未来得及从 USART3 上发出最后一个字节时,已进入了 STOP 模式。检查其软件中,从 USART3 发送报文的代码,表(三)所示:
对其进行修改,将 USART_FLAG_TXE 替换为 USART_FLAG_TC,如表(四)所示:
重新编译、执行。使用示波器观察 STM32 从 USART3 发出的最后一个报文与 PB7 上的信号的相位关 系。结果表明,在 PB7 翻转之前,报文的内容已全部发出,见图(三):
去掉程序中加入的调试代码,恢复进入 STOP 模式的功能,重新测试。STM32 在进入 STOP 模式之前, 发出的最后一个报文是完整的。
结论:
错误使用 USART_FLAG_TXE 作为判断数据在 USART 上发送完成的依据,而导致最后一个字节的数据未及发出即进入了 STOP 模式。
处理:
将 USART_FLAG_TXE 换成 USART_FLAG_TC,作为判定数据在 USART 上发送完的依据。
建议:
在 STM32 状态寄存器 USART_SR 中有两个标志位是和数据发送的完成情况相关的:
1. TXE 发送缓冲区空标志
2. TC 发送完成标志
这两个标志的区别在于:它们分别表示数据在发送过程中,在两个不同的阶段中的完成情况。TXE 表 示数据被从发送缓冲区中取走,转移到的移位寄存器中,此时发送缓冲是空的,可以向其中补充新的 数据了。而 TC 则表示最后放入发送缓冲区的数据已经完成了从移位寄存器向发送信号线 Tx 上的转 移。所以,判定数据最终发送完成的标志是 TC,而不是 TXE。
对应的pdf:UART 发送数据丢失最后一个字节
更多实战经验请看:【ST MCU实战经验汇总贴】
|