// education

인터럽트(Interrupt)와 타이머 활용

프로그램의 메인 루프(loop())를 방해하지 않고 긴급 신호를 감지하는 인터럽트(Interrupt) 제어를 배웁니다.


1. 인터럽트 핵심 용어 사전 (Glossary)


2. 외부 하드웨어 인터럽트 (attachInterrupt)

아두이노 우노는 **디지털 2번(Interrupt 0)**과 3번(Interrupt 1) 핀에서 외부 하드웨어 인터럽트를 지원합니다.

const byte ledPin = 13;
const byte interruptPin = 2;

// ISR 내에서 변경되는 변수는 반드시 volatile 지정!
volatile boolean ledState = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  
  // 2번 핀 전압이 HIGH -> LOW로 떨어지는 순간(FALLING) toggleISR() 즉시 실행
  attachInterrupt(digitalPinToInterrupt(interruptPin), toggleISR, FALLING);
}

void loop() {
  // 메인 루프에서는 딜레이나 무거운 연산을 수행 중이어도 인터럽트는 즉시 반영됨
  digitalWrite(ledPin, ledState);
}

// ISR 함수는 매개변수와 반환값이 없어야 함 (void)
void toggleISR() {
  ledState = !ledState;
}

3. millis() 비동기 멀티태스킹 템플릿

delay()는 CPU를 멈추게 하므로, 여러 개의 작업을 독립적인 주기로 돌리려면 millis() 타임스탬프 비교 방식을 써야 합니다.

unsigned long prevLED = 0;
unsigned long prevSensor = 0;

void loop() {
  unsigned long current = millis();

  // Task A: 0.5초 간격 LED 점멸
  if (current - prevLED >= 500) {
    prevLED = current;
    // LED 작업 수행
  }

  // Task B: 2초 간격 센서 측정
  if (current - prevSensor >= 2000) {
    prevSensor = current;
    // 센서 작업 수행
  }
}

4. 자주 묻는 질문 (Q&A)

Q. ISR 함수 안에서 왜 delay()를 사용할 수 없나요? A. delay() 함수는 아두이노 내부 타이머 인터럽트를 기반으로 시간을 카운팅합니다. 하지만 ISR 함수가 동작하는 동안에는 다른 모든 인터럽트가 차단되므로 delay()의 시간 카운터가 동작하지 않아 무한 대기 상태(Deadlock)에 빠지게 됩니다.

← 이전디지털 통신 인터페이스 (I2C, SPI, 1-Wire) 다음 →나의 첫 번째 아두이노 종합 프로젝트