簡體   English   中英

STM32F4 UART Rx中斷示例代碼

[英]STM32F4 UART Rx Interrupt Example Code

我一直在嘗試使用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中斷只被觸發了一次

不要長時間阻塞HAL_UART_RxCpltCallback 只需設置一個標志並檢查它,然后從main功能發送數據即可。

而且rx_buffer是變量,因此正確調用HAL_UART_Receive_IT(&huart1, &rx_buffer, 1);

對於任何遇到這個問題的人來說,答案都非常簡單。 我有兩個UART,一個使用Rx中斷,另一個使用DMA。

原來我以為我為Interrupt配置的那個實際上是為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完成時生成的中斷),則需要編寫處理循環緩沖區中字符傳輸的代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM