임베디드 시스템

5장 인터럽트와 millis

보름달빵 2024. 6. 16. 11:37

실습과제 

 

 

 

 

 

#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523

#define PIN_PIEZO 10
#define PIN_SWITCH 2 // Button connected to pin 2, 인터럽트 핀 번호 0번 (Int0)
#define PIN_LED 13 // LED connected to pin 13

#define T 200 // 16th note length
#define DB_WAIT 20 // Debouncing wait time

volatile int sw_pressed = 0; // Interrupt flag

void setup() {
  pinMode(PIN_PIEZO, OUTPUT);
  pinMode(PIN_SWITCH, INPUT_PULLUP);
  pinMode(PIN_LED, OUTPUT);
  
  attachInterrupt(0, sw_isr, FALLING); // 버튼이 눌린 순간 인터럽트 함수 실행 
  Serial.begin(9600);
  printMsg("Welcome to John's JukeBox");
}

// Interrupt service routine
void sw_isr() {
  sw_pressed = 1;
}

int Notes[] = { NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5 };
String NoteStr[] = { "Do", "Re", "Mi", "Fa", "Sol", "La", "Si", "Do5" };

void play_note(int n, int d) {
  if (sw_pressed) return; // 버튼이 눌리면 노래 종료  
  Serial.print(NoteStr[n] + " ");
  int duration = T * d; // 노트 지속 시간
  tone(PIN_PIEZO, Notes[n], duration - T * 0.1);
  delay(duration);
}

int airplane_note[] = {2, 1, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 1, 1, 2, 1, 0}; 
int airplane_duration[] = {3, 1, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 3, 1, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4}; 
int airplane_N = 25;

// 비행기 노래 출력 
void play_airplane() {
  for (int i = 0; i < airplane_N; i++) {
    if (sw_pressed) { // 노래 실행 도중 버튼이 눌리면
      sw_pressed = 0; // 리셋
      break; // 노래 종료 
    }
    play_note(airplane_note[i], airplane_duration[i]);
  }
  noTone(PIN_PIEZO); // 재생 중지
}

// 메세지 출력 
void printMsg(const char *str) {
  Serial.print("\r     ");
  Serial.print(str);
}

// led 함수 
void blink() {
  for (int i = 0; i < 10; i++) {
    if (sw_pressed) {
      sw_pressed = 0; // 리셋
      break;
    }
    digitalWrite(PIN_LED, HIGH);
    delay(1000);
    digitalWrite(PIN_LED, LOW);
    delay(1000);
  }
}

int state = 0; // State variable
void loop() {
  switch (state) {
    case 0: // Guide for function 1
      printMsg("Play music?");
      state = 1; 
      break;

    case 1: // Execute function 1
      if(sw_pressed){ // 첫번째 버튼 눌렀을때 
      printMsg("Playing Music....");
      sw_pressed = 0; // 첫번째 버튼에 대한 인터럽트 변수 리셋!! 
      play_airplane(); // 노래 재생
      Serial.print(String("sw_pressed= ")+sw_pressed);
      state = 2; 
      }
     
      break; 

    case 2: // Guide for function 2
      printMsg("Blink the Light?");
      state = 3; 
      break; 

    case 3: // Execute function 2
     if(sw_pressed){
      printMsg("Blinking LED....");
      sw_pressed = 0; // 리셋
      Serial.print(String("sw_pressed= ")+sw_pressed);
      blink();
      state = 0; 
     }
     break; 

    default: 
      break; 
  }
}

 

 

Q 이미 각각의  paly_airplane 과 blink 안에 sw_pressed를 처리하는 부분이 있음에도 불구하고 case문 안에서 sw_pressed를 다시 리셋해주는 이유가 무엇인가 ?

 

Q case문 안에 있는 sw_pressed가 있을때와 없을때의 차이를 생각해보시오