Menu
CoddyTech

volatile로 공유하기

Coddy Arduino 여정의 delay 없이 타이밍 제어하기 섹션에 포함된 레슨. 18개 중 14번째.

ISR은 빠르게 한 가지 작업을 해야 하므로, 보통 스케치의 나머지 부분에서 읽을 변수를 설정합니다. 두 곳에서 모두 사용하는 변수는 volatile로 선언해야 합니다:

volatile bool started = false;

void onPress() {
  started = true;
}

시간을 절약하기 위해 컴파일러(C++ 코드를 칩의 명령어로 변환하는 프로그램)는 메모리를 읽는 대신 프로세서 내부에 변수의 복사본을 보관할 수 있습니다. 컴파일러는 인터럽트가 변수를 바꿀 수 있다는 것을 모르므로 스케치가 오래된 복사본을 계속 사용할 수도 있습니다. volatile을 사용하면 매번 변수를 새로 읽습니다.

이 스케치는 setup()에서 while 루프를 사용해 기다립니다: while (condition) { }은 조건이 참인 동안 중괄호 안의 내용을 반복하며, 여기서 조건은 !started입니다. Inputs 섹션에서처럼 !는 부정을 뜻합니다. 즉, started가 false인 동안 루프가 반복됩니다. volatile이 없으면 버튼을 누른 뒤에도 영원히 기다릴 수 있습니다.

challenge icon

챌린지

쉬움

이 스케치는 버튼을 누를 때까지 기다린 다음 LED를 깜박여야 합니다. 지금은 영원히 기다립니다. 다음과 같이 수정하세요:

  • onPress()에서 started를 true로 설정하세요
  • started를 volatile로 선언하세요

Run을 누르고, 버튼을 누른 다음 Check를 누르세요. 보드가 멈춘 상태로 있는 것을 확인하려면 volatile 없이 한 번 시도해 보세요.

직접 해보기

const int ledPin = 13;
const int buttonPin = 2;

bool started = false;   // 인터럽트에서 설정하고 스케치에서 읽음

unsigned long previousMillis = 0;
int ledState = LOW;

void onPress() {
  // 여기서 started를 true로 설정
}

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);

  // 버튼이 눌릴 때까지 여기서 대기
  while (!started) {
  }
}

void loop() {
  // 250 ms마다 깜빡임
  unsigned long now = millis();
  if (now - previousMillis >= 250) {
    previousMillis = now;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

delay 없이 타이밍 제어하기의 모든 레슨

직접 연습해 보세요: Arduino 플레이그라운드