Я пытаюсь использовать связь UART в режиме прерывания, куда я должен поместить свою функцию?

#c #interrupt #uart #iar #stm32f0

#c #прерывание #uart #iar #stm32f0

Вопрос:

Я новичок в USART-коммуникации, поэтому простите меня, если я задаю глупый вопрос.

Я использую плату STM32F0discovry и кодирую с использованием IAR EWARM. Моя основная функция выглядит следующим образом. У меня также есть функция HAL_UART_RxCpltCallback после основной функции.

 int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  NVIC_EnableIRQ(USART1_IRQn);
  //HAL_UART_Receive_IT(amp;huart1,buffer,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
   
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    //HAL_UART_Receive(amp;huart1,buffer2,10); // unit: milli second
    HAL_UART_Receive_IT(amp;huart1,buffer,1); // unit: milli second
    HAL_Delay(100);
    if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0))
    {
      HAL_UART_Transmit(amp;huart1,buffera,1,100);
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET);
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);
    }
  }
  
  /* USER CODE END 3 */
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
   if(buffer[0] == 'a' )
    {
      HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
    }
    else if(buffer[0] == 'b' )   
    {
      HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET);
    }
    else if(buffer[0] == 'c' )   
    {
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
    }
   //HAL_UART_Receive_IT(amp;huart1,buffer,1); // unit: milli second
}
 

Я читаю несколько руководств и задаюсь вопросом, должен ли я поместить свою функцию в функцию USART1_IRQHandler.

 void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(amp;huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}
 

Или я должен поместить свой код внутри функции HAL_UART_RxCpltCallback?
Я в замешательстве, спасибо, что уделили время чтению этого!

Ответ №1:

void USART1_IRQHandler(void) это фактический обработчик прерываний, который выполняется процессором при запуске IRQ USART1. Он делегирует фактическую работу STM32 HAL путем вызова HAL_UART_IRQHandler(amp;huart1); .

Это HAL_UART_IRQHandler общий обработчик IRQ для всех прерываний UART, поэтому он использует дескриптор UART, чтобы знать, какой UART вызвал прерывание.

The HAL_UART_IRQHandler определяет, какое событие действительно произошло, запрашивая фактические биты состояния UART, которые вызвали прерывание. Исходя из этого, он вызывает фактическую функцию-обработчик.

Затем функция-обработчик выполняет фактическую работу. В случае, если вы начали прием и все запрошенные байты были получены, он вызовет HAL_UART_RxCpltCallback .

Там вы должны проверить, что функция вызывается для ожидаемого UART, а затем вы можете обрабатывать данные.

Существует несколько таких функций обратного вызова, которые можно найти в документации HAL.

Комментарии:

1. Большое спасибо, кодер! Мне также интересно USART1_IRQHandler , что будет вызываться без HAL_UART_Receive_IT функции?

2. @YuechenJiang, да, так и будет. USART1_IRQHandler устанавливается в векторной таблице в качестве обработчика для прерываний USART1. Поэтому всякий раз, когда возникает аппаратное прерывание для USART1, оно будет вызвано. Но без вызова HAL_UART_Receive_IT (или HAL_UART_Reveive_DMA ) HAL не будет знать, что делать, и поэтому никогда не будет вызывать HAL_UART_RxCpltCallback (или какую-либо другую функцию обратного вызова).

3. Большое вам спасибо! Но у меня возникает другой вопрос: кажется, что когда я помещаю свой HAL_UART_Receive_IT inside USART1_IRQHandler , then USART1_IRQHandler никогда не вызывается. это правильный способ сделать это?

4. @YuechenJiang, если мой ответ помог, пожалуйста, примите его. И отсутствие вызова HAL_UART_Receive_IT изнутри обработчика, вероятно, не лучшая идея. Но я не знаю, почему это не удается.

5. Большое спасибо, кодер! Ваша помощь действительно полезна для меня! Надеюсь, у вас отличный день!