中断不将控制权返回给 main

Interrupt not returning control to main

您好,我正在使用 STM32G070 nucleo 板,我正在尝试学习如何使用带有中断的 UART。我在主程序中制作了一个简单的 LED 闪烁程序,在中断处理程序中有一个简单的回声程序。回声正常,但 LED 灯永远不会闪烁。

下面是我的代码:

//while loop for led blinking
while(1)
    {
        
        GPIOA->BSRR     |= (GPIO_BSRR_BS5);
        //delaySys is a blocking delay function that takes milli seconds as input
        delaySys(1000);
        GPIOA->BSRR     &=~(GPIO_BSRR_BS5);
        GPIOA->BSRR     |= (GPIO_BSRR_BR5);
        delaySys(1000);
        
    }
    

接下来是我的中断处理程序

void USART2_IRQHandler()
{
    
    if((USART2->ISR) & (USART_ISR_RXNE_RXFNE))
        {
            
            USART2->TDR = USART2->RDR;
            while(!((USART2->ISR) & (USART_ISR_TC)))
                ;
            NVIC_ClearPendingIRQ(USART2_IRQn);
            
        }
        
    if(((USART2->ISR) & (USART_ISR_TXE_TXFNF)))
    {
        
        //TRANSMISSION COMPLETE
        
        
    }
    
}

如果您期望来自 UART 的后续字节流,可能有时有理由在 ISR 中挂起并进行轮询,直到您获得预期的数量。但是,程序的其余部分将挂断并等待您这样做。

您不需要从 ISR 内部调用 NVIC_ClearPendingIRQ,因为引起中断的标志应该自动清除,通常是通过读取它然后访问数据寄存器等。查看手册的 UART 部分以了解寄存器说明。

在不停止的情况下处理 UART rx 中断的更好但更复杂的方法是使用 DMA。我想大多数STM32应该都支持这个,但我不确定。

然而,查看您的闪烁代码,这是有问题的:

    // light up 1000ms
    GPIOA->BSRR     |= (GPIO_BSRR_BS5);
    delaySys(1000);

    // lights off
    GPIOA->BSRR     &=~(GPIO_BSRR_BS5); 

    // light up some other LED? NOTE: BR5 not BS5
    GPIOA->BSRR     |= (GPIO_BSRR_BR5);
    delaySys(1000);

这可以做以下两件事之一:

  • 如果 GPIO_BSRR_BS5 和 GPIO_BSRR_BR5 是相同的位掩码,那么它点亮 LED 大约 1000ms,然后关闭大约 50-100ns。 LED 在大约 99.99% 的时间内保持点亮。
  • 如果 GPIO_BSRR_BS5 和 GPIO_BSRR_BR5 是不同的位掩码,那么一个 LED 将以 1000 毫秒的占空比闪烁,另一个 LED 将在 100% 的时间内保持点亮。

好的,我确实以某种方式解决了问题。我之前为 tx 启用了中断,但是当我禁用它时,一切正常。似乎 Tx 正在发送中断请求并且正在与 main 竞争。