STM32 HAL UART Transmitir problema de DMA

4

Después de configurar mi proyecto para una placa STM32F7 personalizada que incluye un FT2232H UART < - > convertidor USB, tuve varios problemas al enviar (y recibir datos). El código que uso es generado principalmente por CubeMX y se encuentra al final de la publicación.

En primer lugar, no puedo hacer que el stm transmita a velocidades de transmisión superiores a las del estándar 115200, de acuerdo con las hojas de datos, tanto el FT2232H como el STM32F7 deberían ser capaces de al menos 12M baudios. Para el FT2232H, funciona cuando envío algunos caracteres desde mi terminal (lado USB) y recupero el carácter cuando corté los pines RX y TX en el lado de salida del FT2232H.

La segunda es que no puedo llamar a la función sendUART () varias veces seguidas, ¿por qué no se utiliza el DMA Fifo para almacenar las cosas que quiero enviar?

También, ¿cuál es la forma correcta de recuperar todos los datos recibidos pero hacer uso del fifo para que no se pierdan datos cuando no se sondean a tiempo?

Quizás estas son preguntas tontas, pero ya intenté encontrar una solución aquí y en el resto de Internet, pero no puedo encontrar ninguna.

void MX_UART4_Init(void)
{

  huart4.Instance = UART4;
  huart4.Init.BaudRate = 115200;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspInit 0 */

  /* USER CODE END UART4_MspInit 0 */
    /* UART4 clock enable */
    __HAL_RCC_UART4_CLK_ENABLE();

    /**UART4 GPIO Configuration    
    PA0/WKUP     ------> UART4_TX
    PA1     ------> UART4_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* UART4 DMA Init */
    /* UART4_TX Init */
    hdma_uart4_tx.Instance = DMA1_Stream4;
    hdma_uart4_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_uart4_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_uart4_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_tx.Init.Mode = DMA_NORMAL;
    hdma_uart4_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_uart4_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_uart4_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_uart4_tx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_uart4_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_uart4_tx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmatx,hdma_uart4_tx);

    /* UART4_RX Init */
    hdma_uart4_rx.Instance = DMA1_Stream2;
    hdma_uart4_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart4_rx.Init.Mode = DMA_NORMAL;
    hdma_uart4_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_uart4_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_uart4_rx.Init.MemBurst = DMA_MBURST_SINGLE;
    hdma_uart4_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK)
    {
      _Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(uartHandle,hdmarx,hdma_uart4_rx);

  /* USER CODE BEGIN UART4_MspInit 1 */

  /* USER CODE END UART4_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{

  if(uartHandle->Instance==UART4)
  {
  /* USER CODE BEGIN UART4_MspDeInit 0 */

  /* USER CODE END UART4_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_UART4_CLK_DISABLE();

    /**UART4 GPIO Configuration    
    PA0/WKUP     ------> UART4_TX
    PA1     ------> UART4_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);

    /* UART4 DMA DeInit */
    HAL_DMA_DeInit(uartHandle->hdmatx);
    HAL_DMA_DeInit(uartHandle->hdmarx);
  /* USER CODE BEGIN UART4_MspDeInit 1 */

  /* USER CODE END UART4_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */
void sendUART(char msg[]){
    //HAL_UART_Transmit(&huart4,(uint8_t *) msg, strlen(msg),10000);
    HAL_UART_Transmit_DMA(&huart4,(uint8_t *) msg, strlen(msg));
}

void echo(){
    if(HAL_UART_Receive_DMA(&huart4, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK){}
    else if(HAL_UART_Transmit_DMA(&huart4, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= HAL_OK){
    }
}
    
pregunta JaneDoe

1 respuesta

6
  

En primer lugar, no puedo hacer que el stm transmita a velocidades de transmisión superiores a las del estándar 115200, de acuerdo con las hojas de datos, tanto el FT2232H como el STM32F7 deberían ser capaces de al menos 12M baud.

El hardware admite velocidades de hasta 27 Mbit (bueno, no ha dicho su número de referencia, estoy mirando la hoja de datos del F756), pero según stm32f7xx_hal_uart.h , HAL no aceptará una velocidad superior a 9M

#define IS_UART_BAUDRATE(BAUDRATE) ((BAUDRATE) < 9000001)

Además, depende de la velocidad del reloj del sistema, en la configuración predeterminada, cuando no toca la pestaña Configuración del reloj en STM32CubeMX, todo funciona en el reloj HSI interno de 16 MHz. Eso significa como máximo 1 Mbit mientras usa UART_OVERSAMPLING_16 , o el doble si cambia a UART_OVERSAMPLING_8 (pero luego perdería la detección de ruido).

  

La segunda es que no puedo llamar a la función sendUART () varias veces seguidas, ¿por qué no se utiliza el DMA Fifo para almacenar las cosas que quiero enviar?

Aunque hay un DMA FIFO de 16 bytes, el software no puede acceder a él. No hay manera de agregar solo más datos a una transferencia DMA en curso. HAL no hace nada, pero inicia una transferencia DMA desde la dirección del búfer proporcionada por la persona que llama.

Debe esperar hasta que finalice la transferencia, o suspender el DMA, y seguir esperando hasta que el FIFO esté vacío. Por supuesto, puede asignar un búfer usted mismo, agregar datos a medida que aparezcan y reiniciar DMA cada vez que finalice y haya nuevos datos en el búfer.

  

También, ¿cuál es la forma correcta de recuperar todos los datos recibidos pero hacer uso del fifo para que no se pierdan datos cuando no se sondean a tiempo?

A mí me parece que no puedes tener tanto DMA como interrupciones en cada carácter recibido. Al menos, el valor del registro de estado ISR sería inútil, y el controlador de interrupción no podrá decidir qué hacer. Leerlo podría incluso interferir con la transferencia de DMA. Por lo tanto, debes elegir uno.

Al utilizar DMA para colocar los datos en un búfer (o dos), puede sondear el contador de transferencia regularmente en el bucle inactivo o una interrupción del temporizador. No habrá una respuesta inmediata, pero tal vez no importa en absoluto, porque la interfaz USB también incurrirá en algún retraso.

    
respondido por el berendi

Lea otras preguntas en las etiquetas