본문 바로가기

임베디드 & 로보틱스/STM32

[STM32-기초] 외부 인터럽트(EXTI) 사용해서 LED 상태 토글하기

이전 글에서는 폴링(Polling) 방식으로 B1 USER 버튼의 값을 읽어 누르면 LD1 이 켜지고, 떼면 LD1 이 꺼지는 LED 동작을 만들었습니다.

이번에는 폴링이 아닌 인터럽트(EXTI)를 사용B1상승 엣지(Rising Edge)에서만 LD1 의 상태를 토글해보겠습니다. 의도적으로 디바운싱(Debouncing)을 적용하지 않아 기계식 스위치에서 흔히 발생하는 바운스(Bounce) 현상 또는 채터링(Chattering) 현상이라는 현상을 직접 관찰하는 것이 목표입니다.


Edge란?

더보기
더보기

Rising Edge : 논리 값이 0 에서 1로 올라갈 때
Falling Edge : 논리 값이 1에서 0으로 내려갈 때
STM에서 논리 값 1 = 3.3V


채터링 현상이란?

더보기
더보기

기계식 접점(스위치 or 버튼)이 눌리거나 떼질 때 접점이 몇 ms 동안 빠르게 ON/OFF 값이 튀는 현상. 한 번만 눌러도 여러 번 눌린 것 처럼 인식됨.

 

준비물

  • 개발 보드 :  Nucleo-F746ZG
  • IDE : CubeIDE
  • 마이크로 5 핀 케이블

 

선수지식

2025.08.27 - [임베디드 & 로보틱스/STM32] - [STM32-기초] HAL GPIO, 내장 스위치로 LED ON/OFF

 

[STM32-기초] HAL GPIO, 내장 스위치로 LED ON/OFF

준비물- CubeIDE가 설치된 PC- 개발 보드 : Nucleo-F746ZG- micro 5 pin 케이블 목표Nucleo-F746ZG 개발보드에 내장된 푸쉬 스위치(B1)로 내장 LED(LD1) ON/OFF 선수지식2025.08.26 - [임베디드 & 로보틱스/STM32] - [STM32-기

eaststarn6.tistory.com

 

 

참고자료

https://www.st.com/resource/en/user_manual/um1974-stm32-nucleo144-boards-mb1137-stmicroelectronics.pdf

MB1137.pdf
3.20MB

 


B1 USER 버튼이 눌릴 때마다 LD1 상태 토글(Toggle) 하기

1. Pinout & Configuration 확인/수정

  1. Pinout view에서 하단의 돋보기란에 PB0 입력
  2. PB0GPIO_Output 으로 설정
  3. PB0 의 라벨을 LD1 으로 변경
  4. PC13 클릭 → GPIO_EXTI13 클릭
  5. PC13 의 라벨을 B1 으로 변경
  6. CategoriesSystem CoreGPIO
  7. 아래와 같이 설정 되었는지 확인


2. NVIC 설정

  1. Pinout & ConfigurationCategoriesSystem CoreNVIC 순서대로 클릭
  2. EXTI line[15:10] interrupts체크
  3. 아래와 같이 설정되었는지 확인

 

3. 코드 생성

  1. 상단 ProjectGenerate Code(노란색 톱니바퀴 아이콘)
  2. CoreSrc stm32f7xx_it.c 로 이동
  3. void EXTI15_10_IRQHandler(void) 를 찾아가 보면 HAL_GPIO_EXTI_IRQHandler(B1_Pin); 가 있다.
  4. HAL_GPIO_EXTI_IRQHandler(B1_Pin); 를 더블클릭하고, F3를 눌러서 HAL_GPIO_EXTI_IRQHandler(B1_Pin); 의 선언 부분으로 이동하면
  5. 조금 아래에 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 가 있는 것을 확인할 수 있다.
  6. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)  를 복사 하고 main.c로 이동
  7. 이제 아래와 같이 코드를 작성한다.
/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == B1_Pin) {
		HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
	}
}
/* USER CODE END 4 */

 


4. 동작 영상

간간히 LD1의 상태가 바뀌지 않는 것을 확인할 수 있습니다.

사실 LD1의 상태가 바뀌지 않은게 아니라 B1 버튼에서 발생한 채터링 현상이 디바운싱 되지 않아서 인간이 감지할 수 없는 짧은 시간 동안 상승(Rising) 엣지가 여러번 감지되어 LD1의 상태가 여러번 토글 되었기 때문입니다.

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.


5. 문제 해결하기

이 문제를 해결하기 위해선 엣지(Edge)란 무엇인지, 채터링 현상 또는 바운스 현상이란 무엇인지 이해하고, 디바운싱 처리를 해줘야 합니다.

간단하게 생각하면

채터링 현상은 몇 ms 동안 빠르게 신호가 바뀌는 거라며? 인터럽트 콜백에 약간의 delay를 넣어서 SW적으로 디바운싱 해주면 되는거 아니야?

라고 생각할 수 있습니다. 하지만 인터럽트 콜백 내에는 절대 HAL_Delay와 같은 지연, 블록킹, 반복문 사용, 긴 코드 등을 사용하면 안 됩니다.

 

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == B1_Pin) {
        HAL_Delay(20); // ❌ ISR에서 지연 금지
        HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
    }
}

 

그리고 사실, 콜백내에서 HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); 과 같은 코드도 권장되지 않습니다.