USART关闭不完全导致TC置1引发的代码Bug
错误的代码
// 串口1中断函数
void USART1_IRQHandler(void)
{
if (LL_USART_IsActiveFlag_RXNE(USART1)) // 接收数据
{
........................
}
else if (LL_USART_IsActiveFlag_TC(USART1)) // 发送完成中断
{
LL_USART_ClearFlag_TC(USART1); // 清发送完成中断
..............
}
else
{
LL_USART_ClearFlag_ORE(USART1); // 清除溢出标志
..............
}
}
// 关闭串口1
void USART1_Init_off(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct;
LL_USART_Disable(USART1); // 失能USART1
// USART1引脚配置
GPIO_InitStruct.Pin = USART1_TX_PIN | USART1_RX_PIN; // TX: PC4 RX: PC5
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; // 输入模式
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; // 不上下拉
LL_GPIO_Init(USART1_GPIO_PORT, &GPIO_InitStruct); // 初始化引脚配置
}
现象
我执行关闭串口程序后,单片机不断进入:
else if (LL_USART_IsActiveFlag_TC(USART1)) // 发送完成中断
{
LL_USART_ClearFlag_TC(USART1); // 清发送完成中断
..............
}
导致出现死循环。
解决方案
在关闭串口代码中加入关闭串口中断的代码:
// 关闭串口1
void USART1_Init_off(void)
{
LL_GPIO_InitTypeDef GPIO_InitStruct;
NVIC_DisableIRQ(USART1_IRQn); // 关闭串口中断
LL_USART_Disable(USART1); // 失能USART1
// USART1引脚配置
GPIO_InitStruct.Pin = USART1_TX_PIN | USART1_RX_PIN; // TX: PC4 RX: PC5
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; // 输入模式
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; // 不上下拉
LL_GPIO_Init(USART1_GPIO_PORT, &GPIO_InitStruct); // 初始化引脚配置
}
原因
调用 LL_USART_Disable(USART1) 后,TC 标志被置为 1,串口中断又未关闭,导致死循环。
一、TC 是什么?为什么它在 Disable 后置 1?
TC(Transmission Complete)的定义:
根据 STM32 的官方参考手册:
TC = 1 当 所有发送数据都完成,包括:
TDR(发送数据寄存器)为空,- 移位寄存器也完全把数据移出去了(所有位都发出去了)。
关键点来了:
当你调用 LL_USART_Disable(USART1),也就是将 CR1 的 UE(USART Enable)位置为 0:
- STM32 会自动清除一些状态(比如 TXEIE、RXNEIE 等中断位),
- 但它并不会清除
TC,甚至更重要的是: - 如果发送已经完成,它会立刻把
TC置 1!
也就是说 —— 执行 LL_USART_Disable() 的那一刻,只要没有数据待发,TC 就会变成 1。
二、这种行为是否合理?是否有文档依据?
是的,STM32 的官方参考手册(比如 F1/F4/H7 系列)明确说明了:
“If no transmission is on-going, disabling the USART will result in setting the TC flag.”
翻译:
如果当前没有正在发送的操作,关闭 USART 会导致 TC 被置位。

40

被折叠的 条评论
为什么被折叠?



