简体   繁体   English

HAL_UART_Receive_DMA 只工作一次。 我该如何解决?

[英]HAL_UART_Receive_DMA works only once. How can I fix it?

I am working with STM32F103RB board and I want to simply echo everything I receive from my computer via serial port back to that port.我正在使用 STM32F103RB 板,我想简单地将我通过串行端口从计算机收到的所有内容回显到该端口。 I must do it using UART and DMA.我必须使用 UART 和 DMA 来完成。 I've set up DMA on USART2_RX with CubeMX in normal mode.我已经在正常模式下使用 CubeMX 在 USART2_RX 上设置了 DMA。 My problem is that HAL_UART_RxCpltCallback gets called only once.我的问题是HAL_UART_RxCpltCallback只被调用一次。 Interestingly I get the response on PC end but with additional 0xFC byte.有趣的是,我在 PC 端得到了响应,但有额外0xFC字节。 After that the controller stops reacting to new data sent through the serial port and won't do so until I unplug and plug controller back in with usb. Here is the code for call back and main function:之后 controller 停止对通过串行端口发送的新数据做出反应,直到我将 controller 拔出并重新插入 usb 时才会这样做。这是回调和主要 function 的代码:

#define BUF_SIZE 16

uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
  HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
}

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Edit: I am trying to do this on a Mac through USB-C dongle.编辑:我正在尝试通过 USB-C 加密狗在 Mac 上执行此操作。 Can this be the problem?这可能是问题所在吗?

Calling complex functions in an ISR is a bad idea.在 ISR 中调用复杂函数不是一个好主意。 Many of the HAL functions use the system tick to measure timeouts, and depending on your interrupt priorities, the tick may be blocked while your ISR runs.许多 HAL 函数使用系统节拍来测量超时,并且根据您的中断优先级,节拍可能会在您的 ISR 运行时被阻止。

It would be better to move any complex processing out of your ISR, into the main function. Just set a flag in the ISR to indicate when reception is complete.最好将任何复杂的处理从您的 ISR 移到主 function 中。只需在 ISR 中设置一个标志以指示接收何时完成。 Something like:就像是:

static volatile bool uart_rx_done = false;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    uart_rx_done = true;
}

int main()
{
    // Initialisation stuff

    for (;;)
    {
        uart_rx_done = false;
        HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
        while (!uart_rx_done)
            ;

        HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
    }
}

First of all, check if you configured uart and dma interrupts correctly.首先,检查您是否正确配置了uartdma中断。 in the stm21f1xx_it.c file you should see these functionsstm21f1xx_it.c文件中,您应该会看到这些函数

void DMA1_Channel6_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */

  /* USER CODE END DMA1_Channel6_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart2_rx);
  /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */

  /* USER CODE END DMA1_Channel6_IRQn 1 */
}


void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

and also a uart2 configuration in the MX_NVIC_Init() function in your main.c file.以及main.c文件中的MX_NVIC_Init() function 中的uart2配置。

But your main mistake is that you're not activating uart receive interrupt at all.但是你的主要错误是你根本没有激活uart接收中断。 I suggest not using dma for now, and try this to see if the uart interrupt gets activated:我建议暂时不要使用dma ,试试这个看看uart中断是否被激活:

#define BUF_SIZE 16
bool uart_received = false;

uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  // HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
  uart_received = true;
  HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
}

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  //HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
  HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      if (uart_received) {
          HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
          uart_received = false;
      }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

If this works, then you can use HAL_UARTEx_ReceiveToIdle_DMA for activating uart-dma interrupt and HAL_UARTEx_RxEventCallback for callback function (assuming the dam interrupt is configured).如果这可行,那么您可以使用HAL_UARTEx_ReceiveToIdle_DMA激活uart-dma中断,并使用HAL_UARTEx_RxEventCallback回调 function(假设已配置dam中断)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM