STM32F4 EXTI中断相互干扰
STM32F4 EXTI interrupts interfere with each other
我正在使用 STM32F407VGT6 MCU,但遇到外部中断问题 (EXTI
)。我已经将两个引脚配置为 EXTI
,它们是 PE7
和 PE15
。它们连接到 HALL 传感器驱动器并检测触发轮的嘟嘟声边缘。一个是多齿的主要来源,另一个是确认位置的单齿轮。问题是它们可以毫无问题地独立工作,但如果我将它们连接起来,它们就会开始相互干扰并且我会失去位置同步,因为 MCU 正在检测错误边缘。我可以通过将任一引脚连接到低信号并将其他引脚连接到 HALL 驱动器来重新创建相同的行为。但是,如果我禁用 EXTI
并将 pin 作为输入,问题就会消失。我不知道这里发生了什么。
此外,我之前遇到过 PE15
和 EXTI
的问题,可能与此有关。 EXTI
仅在 EXTI_Trigger_Rising
和 EXTI_Trigger_Rising_Falling
模式下工作,但 EXTI_Trigger_Falling
提供随机边缘检测,唯一的解决方案是监听两个边缘并对一个边缘去抖动我不需要。我在数据表中找不到任何相关信息。
这个STM32F4让我头疼,我运行别无选择。好吧,最后一个选择是将霍尔驱动器重新路由到其他引脚并使用输入 capture/timer.
主轮配置:
void Trigger_Configure_Primary(void) {
// GPIO
GPIOE->OSPEEDR |= (0x03 << (2 * 15)); // high speed
// EXTI
SYSCFG->EXTICR[3] = SYSCFG_EXTICR4_EXTI15_PE; // Tell system that you will use PE15 for EXTI15
EXTI->RTSR |= (1 << 15); // rising edge
EXTI->FTSR |= (1 << 15); // falling edge
EXTI->IMR |= (1 << 15); // Unmask EXTI15 interrupt
EXTI->PR |= (1 << 15); // Clear pending bit
/* Add IRQ vector to NVIC */
NVIC_SetPriority(EXTI15_10_IRQn, 0);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
副轮配置:
void Trigger_Configure_Secondary(void) {
// GPIO
GPIOE->OSPEEDR |= (0x03 << (2 * 7)); // high speed
// EXTI
SYSCFG->EXTICR[1] = SYSCFG_EXTICR2_EXTI7_PE; // Tell system that you will use PE7 for EXTI7
EXTI->RTSR |= (1 << 7); // rising edge
EXTI->FTSR |= (1 << 7); // falling edge
EXTI->IMR |= (1 << 7); // Unmask EXTI7 interrupt
EXTI->PR |= (1 << 7); // Clear pending bit
/* Add IRQ vector to NVIC */
NVIC_SetPriority(EXTI9_5_IRQn, 0);
NVIC_EnableIRQ(EXTI9_5_IRQn);
}
IRQ 处理程序:
void EXTI9_5_IRQHandler(void) {
__disable_irq();
/* Make sure that interrupt flag is set */
if ((EXTI->PR & EXTI_Line7) != 0) {
// Secondary trigger IRQ
uint32_t now_nt = GET_TIMESTAMP();
uint8_t edge = ((GPIOE->IDR & SECONDARY_PIN) == 0 ? 0 : 1);
TD_Decode_Secondary_Trigger_Event(
now_nt,
edge
);
#ifdef DEBUG
// Stats
secondary_ticks = (GET_TIMESTAMP() - now_nt);
#endif
/* Clear interrupt flag */
EXTI->PR |= EXTI_Line7;
++s_cnt;
}
__enable_irq();
}
void EXTI15_10_IRQHandler(void) {
__disable_irq();
/* Make sure that interrupt flag is set */
if ((EXTI->PR & EXTI_Line15) != 0) {
// Primary trigger IRQ
uint32_t now_nt = GET_TIMESTAMP();
uint8_t edge = ((GPIOE->IDR & PRIMARY_PIN) == 0 ? 0 : 1);
if (primary_edge == edge) {
TD_Decode_Primary_Trigger(now_nt);
}
#ifdef DEBUG
// Stats
primary_ticks = (GET_TIMESTAMP() - now_nt);
#endif
/* Clear interrupt flag */
EXTI->PR |= EXTI_Line15;
++p_cnt;
}
__enable_irq();
}
RM0090, 12.3.6 待定寄存器 (EXTI_PR):
This bit is cleared by programming it to ‘1’.
因此,这段代码
/* Clear interrupt flag */
EXTI->PR |= EXTI_Line7;
不仅清除EXTI_Line7
而且清除所有挂起的中断,因为它读取EXTI-PR
和1
for all 触发中断,然后或位 EXTI_Line7
并将 all 写回 1
-es。
使用
/* Clear interrupt flag */
EXTI->PR = EXTI_Line7;
我正在使用 STM32F407VGT6 MCU,但遇到外部中断问题 (EXTI
)。我已经将两个引脚配置为 EXTI
,它们是 PE7
和 PE15
。它们连接到 HALL 传感器驱动器并检测触发轮的嘟嘟声边缘。一个是多齿的主要来源,另一个是确认位置的单齿轮。问题是它们可以毫无问题地独立工作,但如果我将它们连接起来,它们就会开始相互干扰并且我会失去位置同步,因为 MCU 正在检测错误边缘。我可以通过将任一引脚连接到低信号并将其他引脚连接到 HALL 驱动器来重新创建相同的行为。但是,如果我禁用 EXTI
并将 pin 作为输入,问题就会消失。我不知道这里发生了什么。
此外,我之前遇到过 PE15
和 EXTI
的问题,可能与此有关。 EXTI
仅在 EXTI_Trigger_Rising
和 EXTI_Trigger_Rising_Falling
模式下工作,但 EXTI_Trigger_Falling
提供随机边缘检测,唯一的解决方案是监听两个边缘并对一个边缘去抖动我不需要。我在数据表中找不到任何相关信息。
这个STM32F4让我头疼,我运行别无选择。好吧,最后一个选择是将霍尔驱动器重新路由到其他引脚并使用输入 capture/timer.
主轮配置:
void Trigger_Configure_Primary(void) {
// GPIO
GPIOE->OSPEEDR |= (0x03 << (2 * 15)); // high speed
// EXTI
SYSCFG->EXTICR[3] = SYSCFG_EXTICR4_EXTI15_PE; // Tell system that you will use PE15 for EXTI15
EXTI->RTSR |= (1 << 15); // rising edge
EXTI->FTSR |= (1 << 15); // falling edge
EXTI->IMR |= (1 << 15); // Unmask EXTI15 interrupt
EXTI->PR |= (1 << 15); // Clear pending bit
/* Add IRQ vector to NVIC */
NVIC_SetPriority(EXTI15_10_IRQn, 0);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
副轮配置:
void Trigger_Configure_Secondary(void) {
// GPIO
GPIOE->OSPEEDR |= (0x03 << (2 * 7)); // high speed
// EXTI
SYSCFG->EXTICR[1] = SYSCFG_EXTICR2_EXTI7_PE; // Tell system that you will use PE7 for EXTI7
EXTI->RTSR |= (1 << 7); // rising edge
EXTI->FTSR |= (1 << 7); // falling edge
EXTI->IMR |= (1 << 7); // Unmask EXTI7 interrupt
EXTI->PR |= (1 << 7); // Clear pending bit
/* Add IRQ vector to NVIC */
NVIC_SetPriority(EXTI9_5_IRQn, 0);
NVIC_EnableIRQ(EXTI9_5_IRQn);
}
IRQ 处理程序:
void EXTI9_5_IRQHandler(void) {
__disable_irq();
/* Make sure that interrupt flag is set */
if ((EXTI->PR & EXTI_Line7) != 0) {
// Secondary trigger IRQ
uint32_t now_nt = GET_TIMESTAMP();
uint8_t edge = ((GPIOE->IDR & SECONDARY_PIN) == 0 ? 0 : 1);
TD_Decode_Secondary_Trigger_Event(
now_nt,
edge
);
#ifdef DEBUG
// Stats
secondary_ticks = (GET_TIMESTAMP() - now_nt);
#endif
/* Clear interrupt flag */
EXTI->PR |= EXTI_Line7;
++s_cnt;
}
__enable_irq();
}
void EXTI15_10_IRQHandler(void) {
__disable_irq();
/* Make sure that interrupt flag is set */
if ((EXTI->PR & EXTI_Line15) != 0) {
// Primary trigger IRQ
uint32_t now_nt = GET_TIMESTAMP();
uint8_t edge = ((GPIOE->IDR & PRIMARY_PIN) == 0 ? 0 : 1);
if (primary_edge == edge) {
TD_Decode_Primary_Trigger(now_nt);
}
#ifdef DEBUG
// Stats
primary_ticks = (GET_TIMESTAMP() - now_nt);
#endif
/* Clear interrupt flag */
EXTI->PR |= EXTI_Line15;
++p_cnt;
}
__enable_irq();
}
RM0090, 12.3.6 待定寄存器 (EXTI_PR):
This bit is cleared by programming it to ‘1’.
因此,这段代码
/* Clear interrupt flag */
EXTI->PR |= EXTI_Line7;
不仅清除EXTI_Line7
而且清除所有挂起的中断,因为它读取EXTI-PR
和1
for all 触发中断,然后或位 EXTI_Line7
并将 all 写回 1
-es。
使用
/* Clear interrupt flag */
EXTI->PR = EXTI_Line7;