我知道可以使用以下命令启用UART接收中断
HAL_UART_Receive_IT(&huart2, (uint8_t *)rx_buffer, expectedNumberOfBytes)
我们可以使用HAL_NVIC_DisableIRQ()
(例如:HAL_NVIC_DisableIRQ(USART1_IRQn)
)来禁用UART中断。这将防止它引发中断,但是需要将函数HAL_UART_Receive_IT
设置的状态HAL_UART_STATE_BUSY_RX
设置回HAL_UART_STATE_READY
,以使uart句柄返回到以下状态:可以接受新的HAL_UART_Receive_IT()
通话。
问题
如果要在一段时间后禁用Rx中断,该如何重置UART中断的状态?
堆栈溢出问题不解决如何重置状态;我已经提到了以下问题:
我可以使用USART_ClearITPendingBit()
或USART_ITConfig()
,但是它们被STM的HAL库定义为私有函数。那我应该使用它们吗?
答案 0 :(得分:3)
如果[I]希望在一段时间后禁用Rx中断,该如何[重置] UART中断的状态[?]
(例如,请参见“ stm32f4xx_hal_uart.c ”中的用法。)
在执行huart->RxState
,HAL_UART_Receive()
,HAL_UART_Receive_IT()
等(以及许多其他操作)时,uart句柄结构的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 */
}
让我们讨论一下禁用/启用中断的一些层次。
您可以使用以下ARM核心CMSIS调用来禁用/启用所有中断,包括此UART7_IRQHandler()
:
__disable_irq();
__enable_irq();
来源: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);
您只能使用以下命令禁用/启用UART7_IRQHandler()
中断(连接到此中断向量的所有10种uart7中断,包括与Tx有关,与Rx有关,与错误有关等) STM32 HAL调用:
HAL_NVIC_DisableIRQ(UART7_IRQn);
HAL_NVIC_EnableIRQ(UART7_IRQn);
然后,执行与上述相同的操作,只是使用这些调用来禁用/启用中断。
但是,如果深入研究HAL_UART_IRQHandler()
调用的UART7_IRQHandler()
的实现,您会发现它仅调用基于中断的接收处理程序{{1 }},如果同时使用UART_Receive_IT()
位(USART状态寄存器中的“接收不为空”)和USART_SR_RXNE
位(USART控制寄存器1中的“接收不为空中断使能”),都设置了。 USART_CR1_RXNEIE
位在字节进入时置位,并在读取数据寄存器或向其写入零时清除。 您可以完全控制中断使能位来禁用此UART接收中断,如果您手动清除此位,则将禁用接收中断,而不会禁用与该USART相关的任何其他类型的中断。这是最好的方法,因为与此UART相关联的中断源有10个。换句话说,清除该位不仅会导致RXNE
内部的检查失败,而且还会阻止首先收到发生的中断!例如,请参见参考手册RM0090修订版16 :
因此,要仅禁用/启用“ USART接收非空”中断,请执行以下操作。请参阅上面显示的p1013上的控制寄存器(USART_CR1)。
HAL_UART_IRQHandler()
现在,您可以执行以下操作来禁用USART接收中断,重置HAL RxState,然后在准备就绪时再次启动基于中断的接收:
// 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);
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);
进行连续的基于中断的接收。待办事项
HAL_UART_Receive_IT()
毕竟不是真正有用的功能。待办事项
待办事项
答案 1 :(得分:0)
当程序从保持寄存器中读取时,大多数UART清除所有未决的接收中断。所以我的答案是:禁用中断后只需读取数据寄存器,而忽略结果。
我还没有机会在STM32上尝试此操作,但是...
答案 2 :(得分:0)
您可以使用HAL_UART_Abort_IT
。
答案 3 :(得分:0)
有一个函数static void UART_EndRxTransfer(UART_HandleTypeDef *huart)
在执行以下操作的 HAL 库中:
huart->RxState
恢复到就绪状态我在 stm32f7xx_hal_uart.c
文件中找到了该函数。但是,它被定义为 static
,所以我只是将定义复制到我使用它的文件中。这可能有点老套,但对我有用。