STM32F4 UART Rx中断示例代码

时间:2018-08-06 07:48:50

标签: interrupt uart stm32f4

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

非常简单-我想通过Rx中断在UART1中接收一个字符,并在UART 6上传输它

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

    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中启用UART 1 NVIC中断,并且stm32f4xx_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,因为在stm32f4xx_hal_uart.c中定义了UART_Receive_IT()。

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

任何人都没有任何代码可以演示我要实现的目标吗?我的google-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中断只被触发了一次

2 个答案:

答案 0 :(得分:2)

请勿长时间阻止HAL_UART_RxCpltCallback!只需设置一个标志并检查它,然后从main函数发送数据即可。

并且rx_buffer是可变的,因此正确调用HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);

答案 1 :(得分:0)

对于绊倒这个问题的任何人来说,答案都非常简单。我有两个UART,一个是使用Rx中断,另一个是使用DMA。

结果是我认为为Interrupt配置的实际上是为DMA配置的,反之亦然...

在STMCubeMX中  -USART1(RS485)启用了DMA Tx和DMA Rx  -USART6(调试-RS232)启用了全局中断

在main.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完成时生成的中断),则需要编写代码来处理循环缓冲区中字符的传输

相关问题