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 처리 흐름

 

  1. 외부 입력 핀의 Rising,Falling edge 상태 변화를 감지한다.
  2. masking bit로 enable인지 확인 후, pending bit가 1로 설정된다.
    • masking register : 인터럽트를 enable한다.
    • pending register : 외부 인터럽트가 발생했음을 플래그.(rc_w1)
      • 읽기 : 1이면 인터럽트 발생.
      • 쓰기 : 1을 쓰면 0으로 클리어하며 인터럽트 처리 완료.
  1. NVIC에 등록한 IRQ인터럽트 핸들러의 우선순위와 해당 인터럽트를 CPU에 전달하고 ISR(service routine)에 진입한다.
  2. 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);

}

+ Recent posts