안녕하세요.
이전에 GPIO 핀을 이용해서 FND(7-SEG)에 숫자에 맞게 불이 들어오는 제어를 해보았습니다.
FND 코드에 GPIO 글에서 Polling 방식으로 버튼을 처리했던 것을 Interrupt로 바꿔 적용해 보겠습니다.
그래서 최종적으로는 인터럽트 방식의 버튼을 누르면 FND 숫자가 증가하는 것으로 동작시켜 보겠습니다.
1. 외부 인터럽트 처리과정
PC13(EXTI13) 핀에 인터럽트 요청신호가 들어오면 Cortex-M4 NVIC에서 인터럽트를 인지하고 EXTI 인터럽트 벡터주소(0x0000 00E0)로 이동하여 인터럽트 서비스 루틴은 EXTI15_10_IRQHandler() 함수를 호출하고, 다시 HAL_GPIO_EXTI_IRQHandler() 호출하고 다시 HAL_GPIO_EXTI_Callback()가 호출된다는 것을 알 수 있습니다.

EXTI13 인터럽트 서비스 루틴인 EXTI15_10_IRQHandler 함수에는 다음 인터럽트 처리를 위해 Pending 레지스터(EXTI_PR)를 리셋해야 합니다. 해당 인터럽트가 요청되어 활성화되면 Pending 레지스터는 세트 되어 동일한 인터럽트 처리가 되지 않습니다.
Pending 레지스터만 보았지만, 블록 다이어그램을 보면 trigger 선택은 다른 여러 가지 선택할 수 있는 레지스터들이 있다는 것을 알 수 있습니다.

참고로 인터럽트 벡터에 주소를 보면, 15-10은 주소를 확인할 수 있습니다.

2. 프로젝트 복사
이전 글에서 생성한 7-SEG 프로젝트를 복사해서 사용하도록 하겠습니다.
기존에 작업한 폴더를 복사하고 이름을 폴더명을 원하는 이름으로 변경합니다.
폴더명을 변경한 폴더 안에서 Debug 폴더와 .launch 파일은 삭제합니다.
그리고 중요한 .ioc 파일은 이름을 프로젝트 명(위에서 바뀐 이름)과 동일하게 해 줍니다.
CubeIDE에서 "File->Import->General->Existing Projects into Workspace"를 선택하고 수정한 폴더를 추가합니다.

위와 같이 진행하면, 복사한 폴더를 새로운 프로젝트로 사용할 수 있습니다.
3. 스위치를 위한 하드웨어 핀 설정
FND의 GPIO 핀 8개는 GPIO_OUTPUT 모드로 동일하게 설정하고, GPIO 설정에서 PC13의 label을 SW1_INT로 모드는 Rising Edge trigger detection로 변경합니다. NVIC 탭에서 Enabled로 활성화 체크를 합니다.

왼쪽 NVIC 탭의 Code Generation 탭 메뉴에서는 Generate Enable in Init와 Generate IRQ Handler가 체크되어 있는지 확인합니다.

여러 개의 인터럽트 버튼을 사용한다면, Sub Priority 옵션에서 우선순위를 변경할 수 있습니다.

저장하고 코드 생성을 합니다.
4. 코드 확인 및 추가
1) 호출하는 함수 확인
void MX_GPIO_Init(void) 함수를 따라가 보면, EXTI 관련해서 추가된 것을 알 수 있습니다.

그리고 stm32f4xx_it.c 파일을 열어봅니다.
위에서 본 것처럼 인터럽트가 호출되면 void EXIT_IRQHandler(void) 함수가 되고, 다음으로 HAL_GPIO_EXTI_IRQHandler(EXT0_Pin); 함수, __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)로 호출된다는 것을 알 수 있습니다.
2) 코드 추가
코드 추가는 main.c 파일에서 작업합니다.
HAL_GPIO_EXTI_Callback() 함수를 추가해서 간단하게 핀에 인터럽트 신호가 들어왔을 때 LD2의 LED가 토글 되는 것을 확인합니다.
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == SW1_INT_Pin)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
}
정상적으로 토글이 되는 것을 확인했다면, FND와 연동해서 누를 때마다 숫자가 증가하는 코드로 변경합니다.
숫자가 증가하는 값을 저장하기 위해서 전역변수와 버튼이 눌렀을 때 main에서 확인할 수 있게 flag 변수를 선언하고 초기화합니다. 니다.
/* USER CODE BEGIN PV */
bool bSwFlag = false;
int g_iCount = 0;
/* USER CODE END PV */
인터럽터에서는 인터럽트핀을 확인하고 숫자증가와 flag를 true로 만들어 줍니다.
/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == SW1_INT_Pin)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
g_iCount++;
bSwFlag = true;
}
}
main함수의 while문에서 버튼 인터럽터가 들어왔다면 g_iCount을 FND 함수에 전달해서 FND표시합니다.
FND 숫자 변화하는 함수(changeFND())는 이전 글의 내용 그대로 사용합니다.
/* USER CODE BEGIN WHILE */
while (1)
{
if (bSwFlag) {
if(10 <= g_iCount) g_iCount = 0;
changeFND(g_iCount);
bSwFlag = false;
}
5. 실행결과
버튼을 누를 때마다 FND 숫자가 0에서 9까지 변경되는 것을 알 수 있습니다.
그러나 버튼 회로에 cap(캐패시터)이 달려 있어서 채터링(파형 출렁임) 발생을 제거하려고 하지만, 스위치를 눌러보면 한 번에 숫자가 넘어가는 현상을 볼 수 있습니다.
이것은 향후 코드 처리로 막아볼 예정입니다.

감사합니다.
<참고 자료>
1. [도서] STM32CubeIDE를 이용한 CORTEX-M4 기초 및 응용
2. STM32F411RE/mb1136-default-c03_schematic.pdf
'Embedded > STM32' 카테고리의 다른 글
| NUCLEO-C031C6 리뷰 - 저가 저전력 STM32C0 시리즈 보드 (0) | 2025.10.26 |
|---|---|
| STM32 버튼 입력에서 플래그를 활용한 소프트웨어 채터링 약간의 개선 기법 중 한 가지 (0) | 2025.10.04 |
| CORTEX-M4 기초 및 응용, 도서 공부하기 5 - F411RE GPIO 제어 (FND(7-SEG) LED) (7) | 2025.08.31 |
| CORTEX-M4 기초 및 응용, 도서 공부하기 4 - F411RE 유저 버튼 사용하기 (Polling방식) (8) | 2025.08.16 |
| CORTEX-M4 기초 및 응용, 도서 공부하기 3 - F411RE 기본 LED 동작하기 (10) | 2025.08.12 |