0
\$\begingroup\$

I'm using STM32F407 discovery board with a GSM Module.

When I'm transmitting and on receiving data, I get zero data, but on the next transfer, I see that the data that I have to receive is filled out. It's very weird scenario but I don't know why.

Here is the Initialization and everything:

/**
  * @brief UART5 Initialization Function
  * @param None
  * @retval None
  */
static void MX_UART5_Init(void)
{

  /* USER CODE BEGIN UART5_Init 0 */

  /* USER CODE END UART5_Init 0 */

  /* USER CODE BEGIN UART5_Init 1 */

  /* USER CODE END UART5_Init 1 */
  huart5.Instance = UART5;
  huart5.Init.BaudRate = 115200;
  huart5.Init.WordLength = UART_WORDLENGTH_8B;
  huart5.Init.StopBits = UART_STOPBITS_1;
  huart5.Init.Parity = UART_PARITY_NONE;
  huart5.Init.Mode = UART_MODE_TX_RX;
  huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart5.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart5) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART5_Init 2 */

  /* USER CODE END UART5_Init 2 */

}
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

}

MSP:

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

 GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==UART5)
  {
  /* USER CODE BEGIN UART5_MspInit 0 */

  /* USER CODE END UART5_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_UART5_CLK_ENABLE();

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    /**UART5 GPIO Configuration    
    PC12     ------> UART5_TX
    PD2     ------> UART5_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12;
    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_UART5;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    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_UART5;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* UART5_RX Init */
    hdma_uart5_rx.Instance = DMA1_Stream0;
    hdma_uart5_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_uart5_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_uart5_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_uart5_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_uart5_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_uart5_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_uart5_rx.Init.Mode = DMA_NORMAL;
    hdma_uart5_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_uart5_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_uart5_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(huart,hdmarx,hdma_uart5_rx);
    }
    /* UART5 interrupt Init */
    HAL_NVIC_SetPriority(UART5_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(UART5_IRQn);

}

and the piece of code I'm testing:

#define DMA_RX_BUFFER_SIZE 512
uint8_t DMA_RX_Buffer[DMA_RX_BUFFER_SIZE];

     while(1)
       { 

        char *string = "AT\r\n";
        HAL_UART_Transmit(&huart5, (uint8_t *)string, 4, 100);
        HAL_Delay(100);
        HAL_UART_Receive_DMA (&huart5, DMA_RX_Buffer, DMA_RX_BUFFER_SIZE);
        HAL_Delay(100);
       }    

Here is a Follow up with the answer:

while(1)
   { 
      if(tx_uart)
      { 
        tx_uart = 0;
        char *string = "AT\r\n";
        HAL_UART_Transmit_IT(&huart5, (uint8_t *)string, 4);

      }
   }    



void UART5_IRQHandler(void)
{

  /* USER CODE END UART5_IRQn 0 */
  HAL_UART_IRQHandler(&huart5);
  /* USER CODE BEGIN UART5_IRQn 1 */

  /* USER CODE END UART5_IRQn 1 */
} 

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
 if (huart == &huart5)
    {
      tx_uart = 1;
      HAL_UART_Receive_IT(&huart5, DMA_RX_Buffer, 9);
    }
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart == &huart5)
    {
    /* USER CODE BEGIN UART5_IRQn 0 */

   // Parse the buffer
    }
}
\$\endgroup\$
  • 3
    \$\begingroup\$ The reply probably takes longer to arrive than you expect. Using fixed delays in serial code is extremely mistaken. What you should do is read until you get the expected result, an error, or declare a timeout. Note that using DMA is probably not helping you here at all, because the reply likely does not start until the end of the transmission anyway, and your program doesn't look like it will try to do anything else until this stage of the conversation is complete. \$\endgroup\$ – Chris Stratton Oct 24 '19 at 15:07
  • \$\begingroup\$ A baud rate of 115200 will give you a transfer speed of about 11 bytes per millisecond. If your sending routine does this by interrupts in the background, HAL_UART_Transmit() will return almost immediately so you need to consider both messages' lengths: the sent and the received. \$\endgroup\$ – the busybee Oct 24 '19 at 19:49
  • \$\begingroup\$ @ChrisStratton can you check please the new edited post, it works the way I did it above, but I'm not sure if its correct or no \$\endgroup\$ – Andre Oct 25 '19 at 12:01
  • \$\begingroup\$ @thebusybee can you check in the original post with the new way ? \$\endgroup\$ – Andre Oct 25 '19 at 12:01
  • \$\begingroup\$ What is there to check? Do you have any open issue? \$\endgroup\$ – the busybee Oct 25 '19 at 16:15
0
\$\begingroup\$

Probably you don't need a DMA receive, rather an interrupt on receive. Remove the delay routines. This is how it should be done when using half duplex communication.

  1. Make a logic when you want to transmit.
  2. When transmit is done, you get this info by enabling the interrupt, start receive with timeout interrupt
  3. On receive interrupt, parse the received message, set the logic to start transmit again.

DMA receive is used for receiving streaming data, it fills a buffer meanwhile the MCU does the other job. In your scenario it is blocked by HAL_Delay, so it does not make sense. Further, as the DMA is used for streaming, the interrupt is set so that it triggers when the buffer is full or half full, there is no such mechanism to trigger an interrupt if you expect a single message/response.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ Can you please check what I did, it did work, but I fail it's not the correct as you mentioned. You can check it in the original post. \$\endgroup\$ – Andre Oct 25 '19 at 12:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.