STM32:将USART与字符匹配ISR和DMA缓冲区一起使用

问题描述 投票:1回答:1

我正在将STM32L432设备与FreeRTOS和STM32CubeMX一起使用。

我尝试通过基于ASCII协议的USART实现M2M通讯。协议序列的长度可以不同,但​​是具有最大长度和定义的结束字符('\ r'/ 0x0D)。

因此,我考虑过使用DMA收集所有RX-USART数据(如FIFO,并基于USART_ICR_CMCF标志使用地址匹配isr确定结束字符。

初始化USART1并启用地址匹配isr

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1) {
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

    /* USER CODE BEGIN USART1_MspInit 1 */
    USART1->CR2 |= 0x0D000000; // \r 0x0D
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_CM);
  }
}

USART1 isr handler

void USART1_IRQHandler(void) {
  if (USART1->ISR & USART_ISR_CMF) {
    data = USART1->RDR;  
    SET_BIT(USART1->ICR,USART_ICR_CMCF);
  }
  HAL_UART_IRQHandler(&huart1);
}

现在,地址匹配isr工作正常,但是我不知道如何实现DMA / FIFO支持。

BTW:

我很惊讶,该设备不支持USART硬件FIFO。我的想法是使用DMA再现常用的FIFO吗?

stm32 fifo dma usart stm32cubemx
1个回答
0
投票

DMA的要点是在传输的每个字节中都不涉及CPU。如果要为每个字节调用ISR,则将占用CPU的资源,因此,即使有可能,同时启用DMA也不会带来任何性能上的好处。摆脱这两个中的任何一个-每字节中断或DMA。如果您绝对想在到达某个特定字符时对其进行检查,那么DMA便无济于事。

另一种在与DMA一起使用任意长度输入时检测输入结束的流行方法是使用USART空闲中断。当经过一个字节的时间(以当前波特率传输一个字节所需的时间)而没有任何传输时,将触发此中断。在此中断中,您可以将DMA缓冲区的内容传输到另一个存储位置,然后重新初始化DMA以供将来输入和退出。或者,您可以在那里然后在那里处理输入。只要ISR快速完成执行,您就可以在ISR ISR中做任何您想做的事情。

如果您的输入具有大量连续的数据运行,则空闲中断将在很长一段时间后触发,此时您可能已经覆盖了缓冲区。您可以使用其他DMA中断(例如Half Complete和Full Complete)来处理此问题。这样也可以解决。我个人发现这种方法在压力测试过程中存在问题。但是没有理由这样,当我尝试使用它时,我没有足够的时间对其进行调试,但是您会在网上找到有关该技术的文章。

© www.soinside.com 2019 - 2024. All rights reserved.