STM32F4 UART Rx中断示例代码



我一直在尝试使用STMCubeMX版本4.26.0 生成的HAL骨架代码在STM32F4板上实现基本的每字节UART Rx中断

很简单-我想通过Rx中断在UART1中接收一个字符,并在UART6 上传输

我已经成功地实现了我想要实现的轮询版本

uint8_t in_usart1[10];
HAL_StatusTypeDef usart1_status;
usart1_status = HAL_UART_Receive(&huart1, in_usart1, 1, 1);
if (usart1_status != HAL_TIMEOUT)
{
HAL_UART_Transmit(&huart6, in_usart1, 1, 100);
}

我已经在STMCubeMX中启用了UART1 NVIC中断,并且stm32f4x_it.c包含IRQ处理程序,我已经将自己的用户处理程序添加到:

void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
HAX_USART1_IRQHandler(&huart1); /* My Handler */
/* USER CODE END USART1_IRQn 1 */
}

我看过很多关于UART_Receive_IT((的评论,但我怀疑这是基于HAL的旧版本,因为UART_Receive-IT((是在stm32f4x_HAL_UART.c 中定义的

我怀疑我需要启用中断/清除中断标志,因为当我调试时,USART1_IRQHandler((从未被调用

有人有任何代码来展示我正在努力实现的目标吗?我的谷歌foo让我失败了

编辑:我离这儿有点近了。。。在main.c中我添加了(注释是现有代码(

/* USER CODE BEGIN PV */
uint8_t rx_buffer;
/* USER CODE END PV */
...
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)rx_buffer, 10);
/* USER CODE END 2 */

然后创建:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
HAL_UART_Transmit(&huart6, &rx_buffer, 1, 100);
}
}

现在Rx中断被触发了,但它在USART6 Tx上有点古怪,并且Rx中断只触发一次

不要长时间阻塞HAL_UART_RxCpltCallback!只需设置一个标志并进行检查,然后从main函数发送数据。

并且rx_buffer是可变的,所以正确地调用HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);

对于任何偶然发现这个问题的人来说,答案都简单得令人尴尬。我有两个UART——一个我使用Rx中断,另一个使用DMA。

事实证明,我以为我为中断配置的那个实际上是为DMA配置的,反之亦然。。。

在STMCubeMX中-USART1(RS485(已启用DMA Tx和DMA Rx-USART6(调试-RS232(具有启用全局中断的

主要.c

/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(debug_uart(), debug_rx_buffer, BUFFER_SIZE);
HAL_UART_Receive_DMA(rs485_uart(), rs485_rx_buffer, BUFFER_SIZE);
/* USER CODE END 2 */

我有一个user_main.c,它有以下代码:

#include <string.h>
#include "stm32f4xx_hal.h"
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart6;
UART_HandleTypeDef *debug_uart(void)
{
return &huart6;
}
UART_HandleTypeDef *rs485_uart(void)
{
return &huart1;
}
#define BUFFER_SIZE 1
uint8_t debug_rx_buffer[BUFFER_SIZE];
uint8_t debug_tx_buffer[BUFFER_SIZE];
uint8_t rs485_rx_buffer[BUFFER_SIZE];
uint8_t rs485_tx_buffer[BUFFER_SIZE];
static void rs485_tx(uint8_t *tx_buffer, uint16_t len)
{
HAL_UART_Transmit_DMA(rs485_uart(), tx_buffer, len);
}
static void debug_tx(uint8_t *tx_buffer, uint16_t len)
{
HAL_UART_Transmit(debug_uart(), tx_buffer, len, 1000);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == debug_uart())
{
memcpy(rs485_tx_buffer, debug_rx_buffer, BUFFER_SIZE);
rs485_tx(rs485_tx_buffer, BUFFER_SIZE);
HAL_UART_Receive_IT(debug_uart(), debug_rx_buffer, BUFFER_SIZE);
}
else if (huart == rs485_uart())
{
memcpy(debug_tx_buffer, rs485_rx_buffer, BUFFER_SIZE);
debug_tx(debug_tx_buffer, BUFFER_SIZE);
HAL_UART_Receive_DMA(rs485_uart(), rs485_rx_buffer, BUFFER_SIZE);
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == debug_uart())
{
}
else if (huart == rs485_uart())
{
}
}
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
}

memcpy((可能不是严格要求的,但它们确实在所有缓冲区之间提供了一定程度的隔离。从技术上讲,可能应该有信号量来提供更多的保护。。。

请注意,我不使用HAL_UART_Transmit_IT((进行调试UART-如果您想使用HAL_UART _Transmit-IT(即在完成Tx时生成的中断(,您将需要编写代码来处理来自循环缓冲区的字符传输

最新更新