【问题标题】:STM32F4 UART Rx Interrupt Example CodeSTM32F4 UART Rx 中断示例代码
【发布时间】:2019-01-13 03:10:14
【问题描述】:

我一直在尝试使用 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,因为 UART_Receive_IT() 在 stm32f4xx_hal_uart.c 中定义

我的怀疑是我需要启用中断/清除中断标志,因为我在调试时,永远不会调用 USART1_IRQHandler()

有没有人有任何代码来演示我想要实现的目标?我的 google-foo 让我失望了

编辑: 我已经更接近了...在 main.c 我添加了(cmets 是现有代码)

  /* 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 中断只被触发一次

【问题讨论】:

    标签: interrupt uart stm32f4


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      对于任何偶然发现这个问题的人来说,答案非常简单。我有两个 UART - 一个使用 Rx 中断,另一个使用 DMA。

      原来我以为我为中断配置的那个实际上是为 DMA 配置的,反之亦然...

      在 STMCubeMX 中 - USART1 (RS485) 启用了 DMA Tx 和 DMA Rx - USART6 (Debug - 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 完成时生成中断),您将需要编写处理来自循环缓冲区的字符传输的代码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-31
        • 2014-09-12
        • 2021-08-26
        • 2022-08-11
        • 2012-11-11
        • 1970-01-01
        相关资源
        最近更新 更多