임베디드 시스템/라즈베리파이

라즈베리파이 (5) - 스위치를 이용하여 인터럽트를 구성하자

달서비 2022. 7. 7. 17:06

우리가 어플 같은 것을 사용할 때 버튼을 누르면 이벤트를 발생합니다. 이 버튼이 while문안에 다 들어가서 작업을 할 수도 있지만 시간은 흐르는데 메모리등 많은 것을 손해보게됩니다. 이럴 때 우리는 인터럽트를 발생시켜 버튼을 누른 경우 처리합니다. 이번에는 이러한 인터럽트에 대하여 알아보겠습니다.

 

인터럽트란?

timeout - pixabay

인터럽트라는 영어단어(interrupt)에는 '중단시키다'라는 뜻을 가지고 있습니다.  CPU가 프로그램을 실행하고 있을 때, 장치에 예외상황이 발생하여 처리가 필요할 때 기존의 프로그램을 중단시키고 마이크로프로세서가 다른 것을 먼저 처리하는 것을 말합니다.

 

인터럽트를 사용하지 않고 스위치를 제어하려고 할 때에는 항상 대기하는 방식으로 구성을 해야 하므로 성능의 손해가 발생합니다.

 

 

라즈베리파이에서 인터럽트를 적용하는 방법

int wiringPiISR (int pin, int edgeType,  void (*function)(void));

인터럽트를 적용하게 하는 함수는 wiringPiISR이라는 함수입니다. 해당 함수를 사용하기 위해서는 인터럽트로 사용하기 위한 pin을 input으로 사용하여야 합니다. input으로 받고 이벤트가 발생하는 경우에 인터럽트가 발생합니다.

pinMode(pin, INPUT);

핀을 설정한 다음에는 edgeType을 선택합니다.

wiringPiISR의 edge 타입은 아래와 같습니다.

edgeType 설명
INT_EDGE_FALLING pin의 값이 HIGH에서 LOW로 바뀌는 경우에 인터럽트 발생
INT_EDGE_RISING pin의 값이 LOW에서 HIGH로 바뀌는 경우에 인터럽트 발생
INT_EDGE_BOTH pin의 값이 HIGH에서 LOW, LOW에서 HIGH로 바뀌는 경우에 인터럽트 발생

마지막으로 실행시킬 함수를 입력하면 해당 함수를 활용하여 구성할 수 있습니다

 

회로 / 소스코드

#include<stdio.h>
#include<wiringPi.h>

#define LED 5       //BCM 기준 5
#define SW 21       //BCM 기준 21

volatile int sw_onoff=0;

void SW_Interrupt();    // 인터럽트 처리 함수

int main() {

    wiringPiSetupGpio();        // BCM  기준
    
    //초기 핀의 Input, Output을 설정
    pinMode(LED, OUTPUT);
    pinMode(SW, INPUT);
    pullUpDnControl(SW, PUD_UP); //내부 PULL-up저항 (쇼트방지)

    //스위치 인터럽트
    if(wiringPiISR(SW, INT_EDGE_FALLING, &SW_Interrupt) < 0)
        return 1;

    while(1) {
        if(sw_onoff == 1) {
            digitalWrite(LED,1);    //LED 점등
            delay(1000);       //time초 만큼 유지
            digitalWrite(LED,0);
            delay(1000);
        }
    }
}

void SW_Interrupt()  {       // 인터럽트 처리 함수
    delay(100);     // 스위치 bouncing 제거 목적
    if(digitalRead(SW)<1) {
        if(sw_onoff == 1) {
            printf("Switch off\n");
            sw_onoff = 0;
        }
        else {
            printf("Switch on\n");
            sw_onoff = 1;
        }
    }
}

인터럽트로 스위치를 입력하는 것을 통하여 LED를 깜빡깜빡하는 예제를 구성해보겠습니다. 여기서 자세하게 봐야 할 부분은 SW_interrupt()라는 임의로 만든 함수입니다. 전역 변수로 설정한 sw_onoff라는 변수를 이용하여 스위치를 1,0으로 인식시키고 컨트롤한 것을 알 수 있습니다. 또한 edgeType을 INT_EDGE_FALLING으로 설정한 이유는 스위치를 누르고 때는 경우에 HIGH에서 LOW로 신호가 바뀌기 때문에 인터럽트를 발생시킬 수 있습니다.