Как настроить и использовать внешние прерывания в микроконтроллере STM32 с операционной системой FreeRTOS?

Какое место в коде FreeRTOS необходимо использовать для организации прерывания EXTI0 и работы с состоянием нажатой кнопки?
  • 2 ноября 2023 г. 16:39
Ответы на вопрос 1
Для настройки и использования внешних прерываний EXTI (External Interrupt) в микроконтроллере STM32 с операционной системой FreeRTOS необходимо выполнить следующие шаги:

1. Настройте внешний прерывание EXTI для выбранной ножки GPIO, которая будет использоваться для подключения кнопки. Например, если используется ножка PA0, необходимо выполнить следующие шаги:

   a. Включите тактирование нужного порта GPIO (порт A в данном случае) с помощью RCC.

   b. Настройте ножку GPIO на вход со встроенным подтягивающим резистором.

   c. Настройте внешнее прерывание EXTI0 для ножки PA0 с помощью функции HAL_NVIC_SetPriority() и HAL_NVIC_EnableIRQ().

   d. Включите прерывания EXTI0 в контроллере прерываний с помощью функции HAL_NVIC_SetPriority() и HAL_NVIC_EnableIRQ().

2. Определите функцию-обработчик прерывания EXTI. В этой функции вы можете выполнить нужные действия при нажатии кнопки, например, изменить состояние флага или отправить сообщение в очередь.

3. В основной программе создайте задачу FreeRTOS, которая будет использовать функцию xQueueReceive() для ожидания сообщения в очереди. Когда произойдет прерывание EXTI, в функции-обработчике вы можете отправить сообщение в очередь с помощью функции xQueueSendToBackFromISR().

Now, let's see how to organize the EXTI0 interrupt and work with the button state in the FreeRTOS code.

Чтобы организовать прерывание EXTI0 и работать со состоянием нажатой кнопки в FreeRTOS, необходимо использовать функцию-обертку для прерывания EXTI.

1. Вставьте функцию-обертку для прерывания EXTI, установите ее внутри метода HAL_EXTI_Callback(). В этой функции вы можете отправить сообщение в очередь или выполнить другие действия в зависимости от состояния кнопки. Здесь приведен пример кода:

```c
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0)
    {
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET)
        {
            // Кнопка нажата
            // Отправить сообщение в очередь нажатий кнопки
            xQueueSendToBackFromISR(buttonQueue, &buttonPressed, &xHigherPriorityTaskWoken);
        }
        else
        {
            // Кнопка отпущена
            // Отправить сообщение в очередь отпуска кнопки
            xQueueSendToBackFromISR(buttonQueue, &buttonReleased, &xHigherPriorityTaskWoken);
        }
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    }
}
```

2. В основной программе создайте задачу FreeRTOS, которая будет ожидать сообщения в очереди кнопки с помощью функции xQueueReceive(). Здесь можно привести пример кода:

```c
void buttonTask(void *pvParameters)
{
    for (;;)
    {
        // Ожидать сообщение в очереди кнопки
        ButtonMessage message;
        if (xQueueReceive(buttonQueue, &message, pdMS_TO_TICKS(100)) == pdPASS)
        {
            if (message == buttonPressed)
            {
                // Обработка нажатия кнопки
                // ...
            }
            else if (message == buttonReleased)
            {
                // Обработка отпускания кнопки
                // ...
            }
        }
    }
}
```

Где `buttonQueue` - это указатель на очередь кнопки, а `ButtonMessage` -
Похожие вопросы