STM32

STM32 인터럽트와 EXTI 설정

임베디드 친구 2024. 11. 28. 09:17
반응형

오늘은 STM32F429ZI 개발 환경에서 인터럽트를 이해하고, NVIC 설정 및 외부 인터럽트(EXTI)를 이용해 버튼을 제어하는 방법을 소개하려고 합니다. 본 포스팅은 STM32CubeIDE를 기반으로 진행하며, STM32CubeMX 없이 직접 IO 설정 및 EXTI 설정을 하는 방법을 다룹니다. 이를 통해 STM32F429ZI의 인터럽트 구조를 제대로 이해할 수 있도록 하겠습니다.

인터럽트의 기본 개념

인터럽트(Interrupt)는 특정 사건(Event)이 발생했을 때 CPU의 주 실행 흐름을 잠시 멈추고 사건을 처리하기 위한 특별한 함수(Interrupt Service Routine, ISR)를 실행하는 기법입니다. MCU에서 인터럽트는 실시간 처리를 가능하게 하며, 버튼 입력, 타이머 이벤트, 통신 등 다양한 사건 처리에 매우 유용합니다.

STM32F4 시리즈는 여러 개의 인터럽트를 지원하며, 이를 NVIC(Nested Vectored Interrupt Controller)라는 컨트롤러를 통해 제어합니다. NVIC는 각 인터럽트의 우선순위를 설정하고, 필요한 인터럽트를 활성화하거나 비활성화할 수 있는 기능을 제공합니다.

NVIC 설정

NVIC(Nested Vectored Interrupt Controller)는 인터럽트 요청을 관리하는 중요한 구성 요소입니다. 각 인터럽트는 우선순위를 가지며, NVIC를 통해 개별 인터럽트를 활성화하거나 비활성화할 수 있습니다. STM32CubeIDE에서 인터럽트의 우선순위를 설정하고 NVIC에 등록하는 과정이 매우 간단합니다.

EXTI(External Interrupt) - 외부 인터럽트 설정

외부 인터럽트(EXTI)는 외부 장치나 버튼과 같은 외부 신호가 특정 핀에 입력될 때 발생하는 인터럽트입니다. 이번 포스팅에서는 GPIO 핀을 설정하여 버튼을 누를 때 인터럽트가 발생하도록 하는 설정을 다루겠습니다.

아래의 단계에서는 STM32CubeIDE를 사용하여 IO 설정을 진행하며, 버튼을 통한 외부 인터럽트 기능을 구현해 보겠습니다.

STM32CubeIDE를 이용한 IO 설정

STM32CubeIDE에서 IO 설정은 매우 직관적입니다. STM32F429ZI 보드를 설정하기 위해 다음 단계를 따라주시기 바랍니다.

1. 프로젝트 생성 및 칩 선택

STM32CubeIDE를 실행하고 새 프로젝트를 생성합니다. STM32F429ZI 칩을 선택하고 프로젝트를 생성하면 기본적인 프로젝트 구조가 생성됩니다.

2. GPIO 설정

  • Pinout & Configuration 탭에서 버튼으로 사용할 핀을 선택합니다. 예를 들어, GPIO_PIN_13을 외부 인터럽트로 사용할 수 있습니다. 이를 위해 다음과 같이 설정합니다.
    • GPIO13을 클릭하고 GPIO_MODE_IT_FALLING 또는 GPIO_MODE_IT_RISING을 선택합니다. 이는 버튼을 눌렀을 때(하강 엣지) 또는 뗄 때(상승 엣지)에 인터럽트가 발생하도록 설정하는 것입니다.
  • 설정이 완료되면, 오른쪽 탭에서 NVIC 설정으로 이동합니다.

3. NVIC 설정

  • Configuration 탭에서 System Core > NVIC를 선택합니다.
  • 외부 인터럽트(EXINT) 항목을 활성화하고 우선순위를 설정합니다. 우선순위는 기본값으로 두거나, 다른 인터럽트와의 우선순위를 고려해 설정하면 됩니다.

4. 코드 생성 및 구현

설정이 완료되면, 상단의 Generate Code 버튼을 눌러 코드를 생성합니다. 이제 STM32CubeIDE가 자동으로 생성한 기본 코드를 바탕으로 추가 작업을 진행하겠습니다.

EXTI를 이용한 버튼 제어 예제 코드

이제 IO 설정을 바탕으로 외부 인터럽트를 통해 버튼을 제어하는 예제 코드를 작성해 보겠습니다. 여기서는 GPIO_PIN_13에 버튼을 연결하고, LED를 GPIO_PIN_5에 연결해 버튼을 누를 때마다 LED를 토글하도록 하겠습니다.

메인 코드 구조

아래의 코드는 CubeIDE에서 자동 생성된 기본 코드를 포함한 전체 소스입니다. 핵심적인 부분은 GPIO와 EXTI 설정, 그리고 인터럽트 서비스 루틴(ISR)입니다.

#include "main.h"

// LED를 연결할 핀 정의
#define LED_PIN GPIO_PIN_5
#define LED_GPIO_PORT GPIOD

// 버튼 인터럽트 핀 정의
#define BUTTON_PIN GPIO_PIN_13
#define BUTTON_GPIO_PORT GPIOC

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{
  // HAL 라이브러리 초기화
  HAL_Init();

  // 시스템 클럭 설정
  SystemClock_Config();

  // GPIO 초기화
  MX_GPIO_Init();

  // 메인 루프
  while (1)
  {
    // 메인 루프에서는 아무 작업도 하지 않습니다.
    // 버튼이 눌릴 때 인터럽트가 발생합니다.
  }
}

// GPIO 초기화 함수
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  // GPIO 클럭 활성화
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();

  // LED 핀 설정
  GPIO_InitStruct.Pin = LED_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);

  // 버튼 핀 설정 (외부 인터럽트)
  GPIO_InitStruct.Pin = BUTTON_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(BUTTON_GPIO_PORT, &GPIO_InitStruct);

  // NVIC 설정: EXTI15_10 IRQ 활성화
  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

// 인터럽트 서비스 루틴
void EXTI15_10_IRQHandler(void)
{
  // 인터럽트 발생 확인 및 클리어
  if (__HAL_GPIO_EXTI_GET_IT(BUTTON_PIN) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(BUTTON_PIN);

    // LED 상태 토글
    HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
  }
}

void SystemClock_Config(void)
{
  // 시스템 클럭 설정 (기본 설정 사용)
}

코드 설명

1. GPIO 초기화

  • MX_GPIO_Init() 함수에서 LED와 버튼 핀을 초기화합니다. LED 핀은 일반 출력 모드로 설정하고, 버튼 핀은 GPIO_MODE_IT_FALLING 모드로 설정하여 하강 엣지에서 인터럽트가 발생하도록 했습니다.
  • GPIO 클럭을 활성화하고 각 핀의 모드와 풀업/풀다운 설정을 지정하였습니다.

2. NVIC 설정

  • NVIC는 HAL_NVIC_SetPriority()HAL_NVIC_EnableIRQ() 함수를 통해 EXTI 인터럽트를 활성화합니다. 이 함수들은 버튼이 눌릴 때 발생하는 인터럽트를 NVIC가 처리하도록 합니다.

3. 인터럽트 서비스 루틴(ISR)

  • EXTI15_10_IRQHandler() 함수는 EXTI 라인의 인터럽트 요청이 발생했을 때 호출되는 ISR입니다. 이 루틴에서 __HAL_GPIO_EXTI_GET_IT()를 통해 인터럽트 발생 여부를 확인하고, __HAL_GPIO_EXTI_CLEAR_IT()를 통해 인터럽트 플래그를 클리어합니다.
  • 버튼이 눌릴 때마다 LED 핀의 상태를 토글하도록 HAL_GPIO_TogglePin()을 사용합니다.

결론

이번 포스팅에서는 STM32F429ZI의 외부 인터럽트를 설정하고 이를 통해 버튼을 눌렀을 때 LED를 제어하는 예제를 다뤄보았습니다. STM32CubeIDE를 사용하여 GPIO와 NVIC를 설정하고, 직접 코드에 EXTI 핸들러를 구현함으로써 인터럽트의 개념을 깊이 이해할 수 있는 기회가 되었길 바랍니다.

인터럽트를 잘 활용하면 시스템의 실시간성을 높이고, 다양한 외부 사건을 효과적으로 처리할 수 있습니다.

반응형