0
\$\begingroup\$

I am trying to make a project and am planning to use DMA for my UART from one STM32 to another STM32. Here are some details of what am I using:

  • Chip: STM32F107RB
  • debugger and programmer: Atollic for STM and CubeMX

What I am trying to do is that, one of my UART inside my STM32 should be able to detect a character when it received (in this case, it is an 'e' and an 'f'), and from there it should do something, which is just to light an LED for this example.

Here's the thing, I am still trying to learn about DMAs, Interrupts and STMs as well and I have a hard time understanding it.

My approach for this is to use the

HAL_UART_TXCpltCallback 

as you have seen in the code below. It does detect the character, but it can only go once. When I tried to send another character, it just does not respond.

Hence, my question will be: How can I make my STM to detect a character correctly from UART, and can respond correctly? I have a feeling to use something similar like HAL_GPIO_IRQHandler but instead of GPIO, should I use HAL_DMA_IRQHandler?

I tried the DMA IRQ Handler though, but it gives error saying: multiple definition of 'HAL_DMA_IRQHandler'.

I hope I adress it clear and would be very glad in any kind of help from the community!

Thanks in advance for your help and have a great day!

    #include "main.h"

    UART_HandleTypeDef huart1;
    UART_HandleTypeDef huart2;
    UART_HandleTypeDef huart3;
    DMA_HandleTypeDef hdma_usart1_rx;
    DMA_HandleTypeDef hdma_usart1_tx;
    DMA_HandleTypeDef hdma_usart2_rx;
    DMA_HandleTypeDef hdma_usart2_tx;
    DMA_HandleTypeDef hdma_usart3_rx;
    DMA_HandleTypeDef hdma_usart3_tx;

    uint8_t tx1_buff[12], rx1_buff[12], tx2_buff[12], rx2_buff[12], tx3_buff[24], rx3_buff[12];
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_DMA_Init(void);
    static void MX_USART1_UART_Init(void);
    static void MX_USART2_UART_Init(void);
    static void MX_USART3_UART_Init(void);

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){

        HAL_UART_Transmit_DMA(&huart1,tx1_buff,sizeof(tx1_buff));
        HAL_UART_Transmit_DMA(&huart2,tx2_buff,sizeof(tx2_buff));
        HAL_UART_Transmit_DMA(&huart3,tx3_buff,sizeof(tx3_buff));


    }

      void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){

                if(rx3_buff[0] == 'e'){
                    HAL_GPIO_WritePin(GPIOC, red_Pin, GPIO_PIN_SET);
                    rx1_buff[0]='e';
                    return;

                }
                else if (rx3_buff[0] == 'f') {
                    HAL_GPIO_WritePin(GPIOC, red_Pin, GPIO_PIN_RESET);
                    rx1_buff[0] = 'f';
                    return;
                }
                HAL_UART_Receive_DMA(&huart3, rx3_buff, sizeof (rx3_buff));
            }


        int main(void)
        {

          HAL_Init();

          SystemClock_Config();

          MX_GPIO_Init();
          MX_DMA_Init();
          MX_USART1_UART_Init();
          MX_USART2_UART_Init();
          MX_USART3_UART_Init();


          HAL_UART_Transmit_DMA(&huart3,tx3_buff,sizeof(tx3_buff));
          HAL_UART_Receive_DMA(&huart3,rx3_buff,sizeof(rx3_buff));

          HAL_UART_Transmit_DMA(&huart1,tx1_buff,sizeof(tx1_buff));
          HAL_UART_Transmit_DMA(&huart2,tx2_buff,sizeof(tx2_buff));

          HAL_UART_Receive_DMA(&huart1,rx1_buff,sizeof(rx1_buff));
          HAL_UART_Receive_DMA(&huart2,rx2_buff,sizeof(rx2_buff));



          while (1)
          {
              HAL_GPIO_TogglePin(GPIOC, green_Pin);
              HAL_Delay(250);

          }
        }

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.Prediv1Source = RCC_PREDIV1_SOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL2.PLL2State = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the Systick interrupt time 
  */
  __HAL_RCC_PLLI2S_ENABLE();
}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

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

  /* USER CODE END USART1_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

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

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

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

  /* USER CODE END USART3_Init 2 */

}


static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
  /* DMA1_Channel4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
  /* DMA1_Channel5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
  /* DMA1_Channel6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
  /* DMA1_Channel7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);

}
\$\endgroup\$
0
\$\begingroup\$

I strongly suggest forgetting DMA for now. That is a convoluted mess of mixing three UARTs, DMA, Tx/Rx complete callbacks that use ALL uarts regardless of which one was causing the callback. DMA is used mainly for block transfers on many bytes that is either known beforehand how much data there will be or at least for receiving fixed length blocks from an arbitrary stream. It makes no sense to wait for a single keypress using DMA, receiving one byte at a time takes even more time to set things up for each byte than to use just interrupts. I don't even use DMA at 3Mbits/sec (although maybe I should). Just concentrate on one UART at a time, make it receive single bytes via interrupts and then process them, maybe using a ring buffer between interrupt receiving and processing in main loop. Then expand accordingly, and consider DMA if it suits your final purpose.

\$\endgroup\$
  • \$\begingroup\$ I see, thank you for your suggestion! I will try to use interrupts instead of DMA. Hope it works this time! \$\endgroup\$ – Stanleyaley Jun 7 at 8:40

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.