이전 글에서는 폴링(Polling) 방식으로 B1 USER 버튼의 값을 읽어 누르면 LD1 이 켜지고, 떼면 LD1 이 꺼지는 LED 동작을 만들었습니다.
이번에는 폴링이 아닌 인터럽트(EXTI)를 사용해 B1 의 상승 엣지(Rising Edge)에서만 LD1 의 상태를 토글해보겠습니다. 의도적으로 디바운싱(Debouncing)을 적용하지 않아 기계식 스위치에서 흔히 발생하는 바운스(Bounce) 현상 또는 채터링(Chattering) 현상이라는 현상을 직접 관찰하는 것이 목표입니다.
Edge란?
채터링 현상이란?
준비물
- 개발 보드 : 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
참고자료
B1 USER 버튼이 눌릴 때마다 LD1 상태 토글(Toggle) 하기
1. Pinout & Configuration 확인/수정
- Pinout view에서 하단의 돋보기란에 PB0 입력
- PB0 를 GPIO_Output 으로 설정
- PB0 의 라벨을 LD1 으로 변경
- PC13 클릭 → GPIO_EXTI13 클릭
- PC13 의 라벨을 B1 으로 변경
- Categories → System Core → GPIO
- 아래와 같이 설정 되었는지 확인

2. NVIC 설정
- Pinout & Configuration → Categories → System Core → NVIC 순서대로 클릭
- EXTI line[15:10] interrupts에 체크
- 아래와 같이 설정되었는지 확인

3. 코드 생성
- 상단 Project → Generate Code(노란색 톱니바퀴 아이콘)
- Core → Src → stm32f7xx_it.c 로 이동
- void EXTI15_10_IRQHandler(void) 를 찾아가 보면 HAL_GPIO_EXTI_IRQHandler(B1_Pin); 가 있다.
- HAL_GPIO_EXTI_IRQHandler(B1_Pin); 를 더블클릭하고, F3를 눌러서 HAL_GPIO_EXTI_IRQHandler(B1_Pin); 의 선언 부분으로 이동하면
- 조금 아래에 __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 가 있는 것을 확인할 수 있다.
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 를 복사 하고 main.c로 이동
- 이제 아래와 같이 코드를 작성한다.
/* 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); 과 같은 코드도 권장되지 않습니다.
'임베디드 & 로보틱스 > STM32' 카테고리의 다른 글
| [STM32-기초] UART 통신으로 Hello World 찍어보기 (Polling) (0) | 2025.12.10 |
|---|---|
| [STM32-기초] HAL GPIO, 내장 스위치로 LED ON/OFF (1) | 2025.08.27 |
| [STM32-기초] HAL GPIO로 내장 LED 500ms 점멸 (0) | 2025.08.26 |
| cubeIDE 설치 (3) | 2025.08.16 |

