2018년 11월 22일 목요일

ESP32에서 인터럽트 사용하기

ESP32는 26개의 GPIO핀을 인터럽트 소스로 사용할 수 있다.

* 아두이노 우노/메가에서는 인터럽트 소스로 사용할 수 있는 핀이 몇개 안된다.




위의 그림에서 빨간색 사각형 안에 들어있는 GPIO 핀들이 인터럽트 소스로 사용 가능한 핀이다.

아두이노에서 인터럽트를 사용하려면 attachInterrupt() 함수로 인터럽트를 설정해 줘야 한다.

attachInterrupt (digitalPinToInterrupt(GPIO), function, mode);

첫번째 파라미터는 인터럽트 소스로 사용할 GPIO 핀 번호인데 번호를 그냥 사용하지 말고 digitalPinToInterrupt(GPIO) 로 넣어줘야 한다. 예를 들어 GPIO 13을 인터럽트 소스로 사용하려면 digitalPinToInterrupt(13) 을 넣어주면 된다.

두번째 파라미터는 인터럽트가 발생했을 때 호출될 함수(Interrupt Service Routine)의 이름이다.

세번째 파라미터는 인터럽트 발생 조건이다. 총 5가지 모드중에 하나를 선택하면 된다.

* LOW - 인터럽트 핀 상태가 LOW면 인터럽트가 발생
* HIGH - 인터럽트 핀 상태가 HIGH면 인터럽트가 발생
* CHANGE - 인터럽트 핀 상태가 바뀌면 인터럽트가 발생. 즉 HIGH에서 LOW로 바뀌거나, LOW에서 HIGH로 바뀌면 인터럽트가 발생
* FALLING - 인터럽트 핀 상태가 HIGH에서 LOW로 바뀔 때 인터럽트가 발생
* RISING - 인터럽트 핀 상태가 LOW에서 HIGH로 바뀔 때 인터럽트가 발생

그러므로 인터럽트를 사용하는 경우 코드의 구조는 다음과 같이 된다.

// 인터럽트가 발생하면 이 함수가 호출됨
void IRAM_ATTR intSvc() 
{
  // 스위치가 눌렸을 때 원하는 동작 코드를 이 부분에 넣어줌
  Serial.println("# Button pressed");
}
void setup()
{
  ...
  attachInterrupt(digitalPinToInterrupt(13), intSvc, LOW);  // GPIO13번 핀에 연결된 스위치가 눌리면 인터럽트가 발생해 intSvc 함수를 호출하도록 설정
  ...
}

void loop()
{
}

위의 코드를 잘 보면 인터럽트가 발생했을 때 호출될 함수 선언에 IRAM_ATTR 이라는 것이 추가되어 있는것을 알 수 있을 것이다. IRAM_ATTR을 넣어줘야 인터럽트 처리 함수가 RAM에 들어가게 된다. IRAM_ATTR이 없으면 인터럽트 처리 함수가 플래쉬에 들어가게 되어 실행 속도가 느려진다.


위와 같이 연결 해 놓고 스위치를 누를 때 마다 LED가 토글되는 코드는 다음과 같다.

#define LED 25
#define SW 13

volatile boolean gLedState = LOW;
 
void IRAM_ATTR toggle() 
{
  gLedState = !gLedState;
  digitalWrite(LED, gLedState);
}


void setup()
{
  pinMode(SW, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SW), toggle, LOW);  // GPIO13번 핀에 연결된 스위치가 눌리면 toggle 함수를 호출하도록 설정
  pinMode(LED, OTUPUT);
}

void loop()
{
}






댓글 없음:

댓글 쓰기