clm*_*mno 2 c hardware interrupt stm32
我知道可以使用启用 UART 接收中断
HAL_UART_Receive_IT(&huart2, (uint8_t *)rx_buffer, expectedNumberOfBytes)
Run Code Online (Sandbox Code Playgroud)
我们可以使用HAL_NVIC_DisableIRQ()
(例如:)禁用 UART 中断HAL_NVIC_DisableIRQ(USART1_IRQn)
。这将防止它抛出一个中断,但该函数的状态集HAL_UART_Receive_IT
是HAL_UART_STATE_BUSY_RX
需要设置回HAL_UART_STATE_READY
为UART手柄回到可以接受一个新的状态HAL_UART_Receive_IT()
调用。
问题
如果我想在一段时间后禁用 Rx 中断,如何重置 UART 中断的状态?
堆栈溢出问题不涉及如何重置状态;我提到了这些问题:
我可以使用USART_ClearITPendingBit()
orUSART_ITConfig()
但这些被 STM 的 HAL 库定义为私有函数。那么我应该使用它们吗?
如果[我]希望在一段时间后禁用 Rx 中断,我如何[如何]重置 UART 中断的状态[?]
(例如,参见“ stm32f4xx_hal_uart.c ”中的用法。)
huart->RxState
uart 句柄结构的成员实际上仅在执行HAL_UART_Receive()
, HAL_UART_Receive_IT()
, HAL_UART_Receive_DMA()
, (以及许多其他类似的内部函数)等操作时由 HAL 库在内部使用。 如果您手动实现自己的基于中断和环形缓冲区-基于 UART Tx 和 Rx 调用,但是,这是执行此操作的首选方式,此成员完全没有意义,您用它做什么无关紧要,因为它仅在 HAL 库函数调用和 HAL ISR 处理程序中使用(两者都不必使用),并且与寄存器级中断和直接事物无关。
但是,通过在stm32f4xx_hal_uart.c 中挖掘源代码(例如),您可以使用以下几个有效选项:
huart->RxState
为HAL_UART_STATE_READY
:HAL_UART_Init()
。通过检查它的源代码,你会看到它huart->RxState= HAL_UART_STATE_READY;
在返回之前调用。huart->RxState = HAL_UART_STATE_READY;
只要您知道在处理过程中正确停止了基于中断的接收,这是完全有效的。然而,让我们更进一步。
假设您在 STM32F4 上使用 UART7。因此,在您的stm32f4xx_it.c中断处理程序文件中,您将看到 STM32CubeMX 自动生成的以下代码:
/**
* @brief This function handles UART7 global interrupt.
*/
void UART7_IRQHandler(void)
{
/* USER CODE BEGIN UART7_IRQn 0 */
/* USER CODE END UART7_IRQn 0 */
HAL_UART_IRQHandler(&huart7);
/* USER CODE BEGIN UART7_IRQn 1 */
/* USER CODE END UART7_IRQn 1 */
}
Run Code Online (Sandbox Code Playgroud)
让我们回顾一下禁用/启用中断的一些层。
您可以UART7_IRQHandler()
使用这些 ARM 核心 CMSIS 调用禁用/启用所有中断,包括 this :
__disable_irq();
__enable_irq();
Run Code Online (Sandbox Code Playgroud)
来源:https : //stm32f4-discovery.net/2015/06/how-to-properly-enabledisable-interrupts-in-arm-cortex-m/
因此,您可以执行以下操作来禁用中断,重置RxState
,然后在准备好后再次启动基于中断的接收:
__disable_irq();
huart7->RxState= HAL_UART_STATE_READY;
__enable_irq();
HAL_UART_Receive_IT(&huart7, (uint8_t *)rx_buffer, expectedNumberOfBytes);
Run Code Online (Sandbox Code Playgroud)您只能禁用/启用UART7_IRQHandler()
中断(连接到此中断向量的所有 10 种类型的 uart7 中断,包括 Tx 相关、Rx 相关、错误相关等),使用这些 STM32 HAL 调用:
HAL_NVIC_DisableIRQ(UART7_IRQn);
HAL_NVIC_EnableIRQ(UART7_IRQn);
Run Code Online (Sandbox Code Playgroud)
然后,除了使用这些调用来禁用/启用中断之外,执行与上面相同的操作。
HAL_UART_IRQHandler()
但是,如果您深入研究由 调用的 的实现UART7_IRQHandler()
,您会发现它只调用基于中断的接收处理程序UART_Receive_IT()
,如果USART_SR_RXNE
位(“接收非空”,在 USART 状态寄存器中)和的USART_CR1_RXNEIE
位(“接收非空中断使能”时,USART控制寄存器1的内部),有两个组。该RXNE
每当一个字节进入时,位就会设置,并且在您读取数据寄存器或向其写入零时清除。中断启用位是您可以完全控制以禁用此 UART 接收中断的内容,如果您手动清除此位,您将禁用接收中断而不禁用与此 USART 相关的任何其他类型的中断。这是最好的方法,因为有 10 个与此 UART 相关的中断源。换句话说,清除该位不仅会导致内部检查HAL_UART_IRQHandler()
失败,而且还可以防止接收中断发生!请参阅参考手册 RM0090 Rev 16,例如:
因此,要仅禁用/启用 USART 接收非空中断,请执行以下操作。请参阅 p1013 上的控制寄存器 (USART_CR1),如上所示。
// Disable the USART Receive Not Empty interrupt
CLEAR_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE);
// Enable the USART Receive Not Empty interrupt
SET_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE);
Run Code Online (Sandbox Code Playgroud)
现在,您可以执行以下操作来禁用 USART 接收中断,重置 HAL RxState,然后在准备好后再次启动基于中断的接收:
CLEAR_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE);
huart7->RxState= HAL_UART_STATE_READY;
SET_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE); // This call isn't actually necessary, as this bit is set inside `HAL_UART_Receive_IT()` as well
HAL_UART_Receive_IT(&huart7, (uint8_t *)rx_buffer, expectedNumberOfBytes);
Run Code Online (Sandbox Code Playgroud)HAL_UART_Receive_IT()
用于基于中断的连续接收。去做
HAL_UART_Receive_IT()
真的不是一个非常有用的功能。去做
去做