修改名为UART_HyperTerminal_IT的示例以在STM32F4上启用UART接收中断?

huangapple go评论57阅读模式
英文:

Modify the example named UART_HyperTerminal_IT to enable UART reception interrupts on STM32F4?

问题

我正在开发一个使用STM32F4的项目,需要启用UART6接收中断。我已经使用STM32CubeMX启用了UART6,并在STM32CubeMX中启用了NVIC USART6全局中断。

示例 UART_HyperTerminal_IT

我已经按照STM32Cube_FW_F4_V1.27.0包中安装的示例UART_HyperTerminal_IT进行操作。这段代码更新一些,但与此示例代码并没有太大不同。

我想要修改示例以将接收到的UART6的每个字符发送回同一个UART6(回显)。因此,我已经删除了示例中发送数据并等待UART数据的所有代码。

我通过以下代码初始化了UART6:

UartHandle.Instance        = USART6;

UartHandle.Init.BaudRate   = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits   = UART_STOPBITS_1;
UartHandle.Init.Parity     = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
UartHandle.Init.Mode       = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

if(HAL_UART_Init(&UartHandle) != HAL_OK) {
    /* 初始化错误 */
    Error_Handler();
}

上述代码与示例代码非常相似(我只更改了波特率奇偶校验)。

我的中断例程

我在文件stm32f4xx_it.c中定义了USART6_IRQHandler函数,如下所示:

void USART6_IRQHandler(void) {
 	unsigned char ch;
	
	uint32_t isrflags   = READ_REG(huart6.Instance->SR);
	uint32_t cr1its     = READ_REG(huart6.Instance->CR1);	
	
	if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
		huart6.Instance->SR;
		ch = huart6.Instance->DR;
		HAL_UART_Transmit(&huart6, &ch, 1, 1000);
	}

    HAL_UART_IRQHandler(&huart6);
}

在示例的readme文件中,我找到了以下句子:

此示例展示了如何通过中断确保UART数据缓冲区的传输和接收。

这句话说示例中已启用中断,但如果我尝试向UART6发送数据,中断例程USART6_IRQHandler()并不会被调用。

我认为UART6接收中断没有被启用,但如何启用它呢?是否有某个寄存器中的特定位必须设置?

谢谢。

英文:

I'm developing a project with STM32F4 and I need to enable the UART6 receive interrupt. I have used STM32CubeMX to enable the UART6 and in the STM32CubeMX I have enabled the NVIC USART6 global interrupt.

The example UART_HyperTerminal_IT

I have followed the example UART_HyperTerminal_IT which is installed by the package STM32Cube_FW_F4_V1.27.0.
The code is more recent but not so different from this example code.

I would like to modify the example to send back every character received from UART6 on the same UART6 (echo). So I have removed all the code of the example that sends data by the UART and wait data from the UART.

I have initialized the UART6 by the following code:

UartHandle.Instance        = USART6;

UartHandle.Init.BaudRate   = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits   = UART_STOPBITS_1;
UartHandle.Init.Parity     = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
UartHandle.Init.Mode       = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

if(HAL_UART_Init(&UartHandle) != HAL_OK) {
    /* Initialization Error */
    Error_Handler();
}

The previous code is very similar to the example code (I have changed only baud rate and the parity).

My interrupt routine

I have defined the function USART6_IRQHandler in the file stm32f4xx_it.c as in the code below:

void USART6_IRQHandler(void) {
 	unsigned char ch;
	
	uint32_t isrflags   = READ_REG(huart6.Instance->SR);
	uint32_t cr1its     = READ_REG(huart6.Instance->CR1);	
	
	if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
		huart6.Instance->SR;
		ch = huart6.Instance->DR;
		HAL_UART_Transmit(&huart6, &ch, 1, 1000);
	}

    HAL_UART_IRQHandler(&huart6);
}

In the readme file of the example I have found this sentence:
>This example shows how to ensure UART Data buffer transmission and reception with
Interrupt.

The sentence says that in the example the Interrupt is enabled, but if I try to send data to the UART6 the interrupt routine USART6_IRQHandler() is not called.

I think that the UART6 Receive Interrupt is not enabled, but how can I enable it? Is there a specific bit in some register that must be set?

Thanks


This post on SO speak about this topic but I think is too old for my STM32F4.

This other post is old too.

答案1

得分: 0

感谢 @pmacfarlane 的评论,我解决了在示例 UART_HyperTerminal_IT 中缺少接收中断的问题。

所以我确认,要获得从UART6接收的字符的回显所需的唯一修改是添加指令 huart6.Instance->CR1 |= USART_CR1_RXNEIE;

启用接收中断的UART6初始化

因此,UART6的初始化代码如下:

huart6.Instance        = USART6;

huart6.Init.BaudRate   = 115200;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits   = UART_STOPBITS_1;
huart6.Init.Parity     = UART_PARITY_NONE;
huart6.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
huart6.Init.Mode       = UART_MODE_TX_RX;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;

if(HAL_UART_Init(&huart6) != HAL_OK) {
    /* 初始化错误 */
    Error_Handler();
}

// 启用接收中断
huart6.Instance->CR1 |= USART_CR1_RXNEIE;

注意。 在前面的代码中,我用变量 UART_HandleTypeDef huart6 替代了在 UART_HyperTerminal_IT 示例中使用的变量 UART_HandleTypeDef UartHandle

中断例程实现回显

在问题中提到的中断例程的代码保持不变:

void USART6_IRQHandler(void) {
    unsigned char ch;
    
    uint32_t isrflags   = READ_REG(huart6.Instance->SR);
    uint32_t cr1its     = READ_REG(huart6.Instance->CR1);   
    
    if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
        huart6.Instance->SR;
        ch = huart6.Instance->DR;
        HAL_UART_Transmit(&huart6, &ch, 1, 1000);
    }

    HAL_UART_IRQHandler(&huart6);
}

USART6_IRQHandler() 函数检索接收到的字符并立即将其发送回去,实现了每个接收到的字符的回显。

空的 while 循环

这就是全部,while(1) 循环完全为空:

while(1) {
   // 空循环
}
英文:

Thanks to @pmacfarlane's comment I solved the problem of the lack of reception interrupts in the example UART_HyperTerminal_IT.

So I confirm that the only modification needed to obtain the echo of the characters receives from UART6 is the addition of the instruction huart6.Instance->CR1 |= USART_CR1_RXNEIE;.

Initialization of UART6 with reception interrupts enabled

So the initialization code for the UART6 becomes:

huart6.Instance        = USART6;

huart6.Init.BaudRate   = 115200;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits   = UART_STOPBITS_1;
huart6.Init.Parity     = UART_PARITY_NONE;
huart6.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
huart6.Init.Mode       = UART_MODE_TX_RX;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;

if(HAL_UART_Init(&huart6) != HAL_OK) {
    /* Initialization Error */
    Error_Handler();
}

// ---> enable reception interruptions
huart6.Instance->CR1 |= USART_CR1_RXNEIE;

Note. In the previous code I have substituted the variable UART_HandleTypeDef UartHandle used in the UART_HyperTerminal_IT example with the variable:

UART_HandleTypeDef huart6;

Interrupt routine implements echo

The code of the interrupt routine presented in the question remains exactly the same:

void USART6_IRQHandler(void) {
    unsigned char ch;
    
    uint32_t isrflags   = READ_REG(huart6.Instance->SR);
    uint32_t cr1its     = READ_REG(huart6.Instance->CR1);   
    
    if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
        huart6.Instance->SR;
        ch = huart6.Instance->DR;
        HAL_UART_Transmit(&huart6, &ch, 1, 1000);
    }

    HAL_UART_IRQHandler(&huart6);
}

The USART6_IRQHandler() function retrieves the received char and sends it immediately back implementing the echo of every char received.

While loop empty

That's all, the while(1) loop is completly empty:

while(1) {
   // empty loop
}

huangapple
  • 本文由 发表于 2023年2月8日 18:09:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75384204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定