中断不将控制权返回给 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 竞争。
您好,我正在使用 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 竞争。