在STM32的标准外设库(SPL)中,EXTI_GetITStatus()
函数访问 EXTI->PR
(挂起寄存器)时,不会自动清除对应的中断标志位。具体行为如下:
1. EXTI_GetITStatus()
的源码分析
以下是标准库中的典型实现(以STM32F10x为例):
c
复制
下载
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) { ITStatus bitstatus = RESET; uint32_t enablestatus = 0; // 1. 检查中断线是否使能(读取 EXTI->IMR) enablestatus = EXTI->IMR & EXTI_Line; // 2. 检查中断是否挂起(读取 EXTI->PR) if (((EXTI->PR & EXTI_Line) != RESET) && (enablestatus != RESET)) { bitstatus = SET; // 中断已触发且使能 } else { bitstatus = RESET; // 中断未触发或未使能 } return bitstatus; }
-
关键点:
-
函数仅通过 读取
EXTI->PR
来检查中断标志位,不会主动清除标志。 -
清除标志需要额外调用
EXTI_ClearITPendingBit(EXTI_Line)
。
-
2. PR寄存器的硬件行为
-
STM32的硬件设计:
-
对
EXTI->PR
的 读操作不会自动清除标志位。 -
清除标志的两种方式:
-
手动写入1:向
EXTI->PR
的对应位写1(如EXTI->PR = EXTI_Line0;
)。 -
调用库函数:
EXTI_ClearITPendingBit(EXTI_Line)
内部会执行写1操作。
-
-
-
示例代码:
c
复制
下载
if (EXTI_GetITStatus(EXTI_Line0) != RESET) { // 处理中断 EXTI_ClearITPendingBit(EXTI_Line0); // 必须手动清除标志! }
3. 与其他寄存器的区别
-
部分STM32外设(如定时器的
SR
寄存器)在读取状态位时会自动清除标志,但 EXTI的PR寄存器不属于这种情况。 -
EXTI的设计初衷:允许用户在确认中断后灵活控制清除时机,避免丢失中断事件。
4. 注意事项
-
必须手动清除标志:
-
若未清除
EXTI->PR
,该中断会持续触发(导致重复进入中断服务函数)。
-
-
清除方式的安全性问题:
-
直接操作寄存器:
EXTI->PR = EXTI_Line;
(写1清除)。 -
使用库函数:
EXTI_ClearITPendingBit(EXTI_Line)
(推荐,可读性更好)。
-
-
HAL库的类似函数:
-
HAL库中的
HAL_EXTI_GetIT()
同样不会自动清除标志,需调用HAL_EXTI_ClearPending()
。
-
5. 总结
行为 | EXTI_GetITStatus() | EXTI_ClearITPendingBit() |
---|---|---|
访问寄存器 | 读取 EXTI->PR 和 EXTI->IMR | 写入 EXTI->PR (写1清除) |
是否清除标志 | 否 | 是 |
硬件自动清除 | 不支持 | 需显式操作 |
结论:
-
EXTI_GetITStatus()
不会自动清除PR寄存器的标志位,必须在中断服务函数中手动清除,否则会导致中断重复触发。