STM32cubeIDE에서 NUCLEO-STM32F429ZI 보드를 사용했습니다.
KEY 버튼을 누를 때마다 LED를 ON OFF 번갈아 깜박거리도록 코드 구현하기.
->GPIO INPUT으로 설정하기 다음으로, 이번엔 Key입력을 GPIO와 연결된 External Interrupt로 구현하기입니다.

1. Key 버튼 위치 확인

)

입력받을 KEY의 핀 위치는 Port C 13번이며 peripheral configuration에서
외부 인터럽트로 사용함으로 EXTI13을 선택한다.
2. EXTI ,SYSCFG 연결

SYSCFG(System config)를 통해 GPIO 해당 포트와 EXTI라인을 연결할 수 있다.
레퍼런스의 mapping 그림을 보면 GPIO핀에 연결 가능한 EXTI0~15개의 16개 라인과 특수 기능용 내부 이벤트에 사용하는 나머지 7개로 총 23개 라인이 있다.
GPIO C 13번 key 핀으로 인한 외부 인터럽트는 EXTI13라인과 연결되어있다.(데이터시트 확인가능)
3.External interrupt 처리 흐름


- 외부 입력 핀의 Rising,Falling edge 상태 변화를 감지한다.
- masking bit로 enable인지 확인 후, pending bit가 1로 설정된다.
- masking register : 인터럽트를 enable한다.
- pending register : 외부 인터럽트가 발생했음을 플래그.(rc_w1)
- 읽기 : 1이면 인터럽트 발생.
- 쓰기 : 1을 쓰면 0으로 클리어하며 인터럽트 처리 완료.
- NVIC에 등록한 IRQ인터럽트 핸들러의 우선순위와 해당 인터럽트를 CPU에 전달하고 ISR(service routine)에 진입한다.
- ISR 끝에서 pending 비트를 1로 써서 클리어해주고 조건을 구현한다.
4. 사용 레지스터
4-1 SYSCFG 클럭 인가

4-2 SYSCFG로 GPIO C포트와 EXTI13라인 연결

4-3 인터럽트 마스킹

4-4 Rising/Falling trigger 설정

)

버튼 핀은 R58 pull down 저항이 있는 회로로,
누르면 High(1)→Rising edge
떼면 Low(0)→Falling edge로,
누를때마다 LED 토글을 하는 것이면 Rising/Falling 둘 중 하나 감지해도 된다.
4-5 NVIC에 해당 IRQ 핸들러 등록하기

EXTI10 - 15을 처리하는 40번 IRQ 핸들러를 사용한다.

NVIC에 이 EXTI15_10 핸들러를 등록하려면
32 ~63 범위인 ISER[1]에 40-32 =8번째 비트에 써서 등록한다.
4-6 Pending bit로 인터럽트 상태 확인+조건 구현

인터럽트가 발생 중이면 1을 읽을 수 있다.
1을 확인 하면
다시 1을 써주어 0으로 클리어해 인터럽트 처리완료와 LED 토글동작을 수행한다.
처음 설정 마무리 시에도 PR을 1로 써주어 리셋하고 while문을 실행한다.
rc_w1관련 의미

비트 처리 방식이 rc_w1인 pending 레지스터의 비트 설정 시 주의사항
예를 들어 인터럽트를 하나 처리하고자
EXTI->PR |= 0x1<<3 이렇게 했을 때, 두 개 이상의 다른 인터럽트도 발생했다면
모두 처리해버리는 문제가 생긴다.
EXTI->PR =EXTI->PR | (0x1<<3)으로 3번 비트에 연결된 하나의 인터럽트를 처리하고자 했을때,
or 연산이여서 1인 플래그가 두 개이다.
이걸 그대로 EXTI->PR에 다시 넣어주게 되면 rc_w1이라 다른 인터럽트의 비트에도 1을 써주는 동작이 된다. 그래서 처리하고자 하지 않았던 비트도 모두 0으로 클리어된다.
EXTI->PR = 0x1<<3 으로 하나의 비트에만 넣어주는 것으로 한다.
5. 위 레지스터 제어로 코드 구현
void led_gpio_init(void){
RCC->AHB1ENR |= (0x1<<1);//GPIOB
GPIOB->MODER &= ~(0x3<<7*2);//LED output mode
GPIOB->MODER |= (0x01 <<7*2);
GPIOB->BSRR=(0x01<<(7+16));
RCC->AHB1ENR |= (0x1 << 2); // GPIOC
GPIOC->MODER &= ~(0x3 << (2 * 13)); // PC13: 입력 모드
}
void exti_init(void){
RCC->APB2ENR |= (1 << 14); // SYSCFG
SYSCFG->EXTICR[3] &= ~(0xF << 4); // EXTI13 위치는 EXTICR[3]의 4~7bit
SYSCFG->EXTICR[3] |= (0x2 << 4); //Port C = 0010
EXTI->IMR |= (1 << 13); // 인터럽트 마스크 (Unmask)
EXTI->RTSR |= (1 << 13); // 버튼누르면 High->rising edge
//Falling edge로 FTSR로 설정해도 토글 동작함.
///누르면 high(rising), 떼면 Low(falling) 어느 엣지든 감지하도록 함.
EXTI->PR = (1 << 13);//인터럽트 플래그 리셋
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI->PR & (0x1<<13)){
EXTI->PR = (1 << 13);//클리어
GPIOB->ODR^=0x1<<7;
}
}
int main(void)
{
HAL_Init();
led_gpio_init();
NVIC->ISER[1]|=0x1<<8;//EXTI15_10->40번
exti_init();
SystemClock_Config();
while (1);
}'Cortex-M' 카테고리의 다른 글
| TIM9 구조와 활용, 익셉션(인터럽트)활용, PWM 파형 출력 (로직 애널라이저) (0) | 2025.05.25 |
|---|---|
| TIM6 타이머 -polling, 익셉션 핸들러(인터럽트) 이용 | STMF429ZI (0) | 2025.05.25 |
| IWDG Independent watch dog | 레지스터 제어로 코드 구현(STM32F429ZI) (0) | 2025.05.23 |
| SysTick 타이머 동작 및 레지스터 이해 | STM32F42ZI (1) | 2025.05.23 |
| UART 시리얼 통신, 로직 애널라이저 파형 출력, 레지스터 제어 구현하기 | STM32F429ZI (2) | 2025.05.23 |