DMA-, Interrupt- und UART-Verbindung in STM32 zum Erkennen von Zeichen

Ich versuche, ein Projekt zu erstellen und plane, DMA für meinen UART von einem STM32 zu einem anderen STM32 zu verwenden. Hier sind einige Details darüber, was ich verwende:

  • Chip: STM32F107RB
  • Debugger und Programmierer: Atollic für STM und CubeMX

Einer meiner UARTs in meinem STM32 sollte in der Lage sein, ein Zeichen zu erkennen, wenn es empfangen wird (in diesem Fall ist es ein 'e' und ein 'f'). Dann sollte es von dort aus etwas tun, nämlich nur eine LED für dieses Beispiel zum Leuchten bringen.

Hier ist die Sache ... Ich versuche immer noch, etwas über DMAs, Interrupts und STMs zu lernen, und es fällt mir schwer, es zu verstehen.

Mein Ansatz dafür ist die Verwendung von:

HAL_UART_TXCpltCallback 

wie Sie im folgenden Code gesehen haben. Es erkennt das Zeichen, aber es kann nur einmal gehen. Als ich versuchte, ein anderes Zeichen zu senden, reagiert es nicht.

Daher meine Frage:

Wie kann ich mein STM dazu bringen, ein Zeichen korrekt von UART zu erkennen und korrekt zu reagieren?

Ich habe das Gefühl, dass ich etwas Ähnliches wie HAL_GPIO_IRQHandler verwenden muss, aber sollte ich anstelle von GPIO HAL_DMA_IRQHandler verwenden ?

Ich habe den DMA IRQ Handler ausprobiert, aber er gibt einen Fehler aus, der besagt: Mehrfachdefinition von 'HAL_DMA_IRQHandler'.

Ich hoffe, ich habe es klar genug angesprochen und würde mich über Vorschläge aus der Community freuen.

    #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);

}

Antworten (1)

Ich empfehle dringend, DMA vorerst zu vergessen. Das ist ein verworrenes Durcheinander, drei vollständige Rückrufe von UARTs, DMA, Tx/Rx zu mischen, die ALLE Uarts verwenden, unabhängig davon, welcher den Rückruf verursacht hat. DMA wird hauptsächlich für Blockübertragungen auf vielen Bytes verwendet, bei denen entweder im Voraus bekannt ist, wie viele Daten vorhanden sein werden, oder zumindest zum Empfangen von Blöcken fester Länge aus einem beliebigen Strom. Es macht keinen Sinn, mit DMA auf einen einzigen Tastendruck zu warten, da der Empfang von jeweils einem Byte noch mehr Zeit benötigt, um die Dinge für jedes Byte einzurichten, als nur Interrupts zu verwenden. Ich verwende nicht einmal DMA mit 3 Mbit/s (obwohl ich das vielleicht tun sollte). Konzentrieren Sie sich einfach auf jeweils einen UART, lassen Sie ihn einzelne Bytes über Interrupts empfangen und verarbeiten Sie sie dann, möglicherweise unter Verwendung eines Ringpuffers zwischen Interrupt-Empfang und Verarbeitung in der Hauptschleife. Dann entsprechend erweitern,

verstehe, danke für deinen Vorschlag! Ich werde versuchen, Interrupts anstelle von DMA zu verwenden. Hoffe es klappt diesmal!
Hervorragende Antwort - ein DMA-Abschluss-Interrupt für ein Zeichen würde fast genauso lange dauern wie ein Zeichen-Rx-Interrupt, jedoch mit dem gesamten Einrichtungsaufwand: (