본문 바로가기

ESP32

ESP32 타이머 및 타이머 인터럽트

반응형

 

ESP32 타이머 및 타이머 인터럽트 

 

ESP32 타이머 및 타이머 인터럽트

 

 

때때로 무언가가 제 시간에 일어나야 할 때가 있는데, 바로 이때 타이머와 타이머 인터럽트가 등장합니다. 타이머는 일종의 인터럽트입니다. 타이머는 시간 이벤트를 측정하고 제어하여 정확한 시간 지연을 제공하는 데 사용되는 간단한 시계와 같습니다. 대부분의 마이크로컨트롤러에는 시간 지연을 생성할 뿐만 아니라 카운터로도 사용되는 내장 타이머가 있습니다. 타이머의 이러한 특성은 많은 애플리케이션에 사용됩니다. 마이크로컨트롤러의 타이머는 타이머 작업에 할당된 특수 기능 레지스터에 의해 제어됩니다.

 

ESP32 타이머

 

ESP32 칩에는 두 개의 하드웨어 타이머 그룹이 있습니다. 각 그룹에는 두 개의 범용 하드웨어 타이머가 있습니다. 이들은 모두 16비트 프리스케일러와 64비트 업/다운 카운터를 기반으로 하는 64비트 일반 타이머로, 자동 재로드가 가능합니다.

 

타이머 인터럽트

 

타이머 인터럽트는 밀리초 단위로 타이밍 이벤트가 발생하도록 보장하는 효과적인 방법으로, 미세 조정된 클록 또는 PWM 작업을 허용하거나 LED에 안정적인 펄스를 공급합니다. 타이머 인터럽트는 타이머가 생성하는 소프트웨어 인터럽트입니다. 타이머 인터럽트를 사용하면 코드에서 다른 작업이 진행 중이든 관계없이 매우 구체적으로 정해진 간격으로 작업을 수행할 수 있습니다. 외부 인터럽트와 유사하지만 외부 이벤트에 의해 트리거되는 대신 타이머에 의해 트리거됩니다. 트리거되면 현재 명령어가 완료된 후 실행 스레드를 중단하고 ISR을 호출하며 완료되면 하드웨어 또는 외부 인터럽트와 마찬가지로 중단된 지점에서 다음 명령어로 돌아갑니다. 타이머 개념을 보여주는 이미지가 있습니다.

 

ESP32 타이머 인터럽트

 

이러한 타이머는 하드웨어 기반이므로 모든 타이밍은 타이머의 클록과 관련이 있습니다. 타이머 속도는 다음 공식으로 결정할 수 있습니다.

 

타이머 속도(Hz) = 타이머 클록 속도(MHz) / 프리스케일러

 

timer speed (Hz) = Timer clock speed (Mhz) / prescaler

 

예를 들어, 클록 주파수가 80MHz인 ESP32의 타이머 속도는 프리스케일러 값이 1인 경우 80MHz 또는 8000000MHz가 되고 프리스케일러 값이 80인 경우 1MHz 또는 1000000Hz가 됩니다.

 

프리스케일러는 위의 주파수를 나누어 타이머의 "틱"(카운터 증가)을 형성합니다. 그런 다음 ISR은 특정 수의 틱 후에 트리거되도록 구성됩니다. 다음 이미지는 타이머 인터럽트가 있는 프로세스 흐름을 보여줍니다.

 

ESP32 타이머 흐름 차트

 

하드웨어 인터럽트와 마찬가지로 타이머 인터럽트는 특정 간격으로 비차단 기능을 실행하는 가장 좋은 방법이기도 합니다. 이를 위해 설정 기능에서 특정 타이머 인터럽트를 구성하여 특정 ISR에 연결합니다. 컨트롤러는 메인 루프를 지속적으로 실행합니다. 타이머 인터럽트가 생성될 때마다 마이크로컨트롤러는 메인 루프를 일시 중지하고 인터럽트 서비스 루틴 또는 ISR의 실행을 진행합니다. ISR이 실행을 마치면 마이크로컨트롤러는 일시 중지된 지점에서 메인 루프를 재개합니다. 이 프로세스는 모든 타이머 인터럽트에 대해 반복됩니다.

 

ESP32 타이머 인터럽트에 대한 일반적인 질문

 

Q. ESP32에는 몇 개의 타이머가 있습니까?

 

ESP32는 64비트 타이머를 4개 제공합니다.

 

Q. ESP32에서 타이머 인터럽트를 사용하는 방법은 무엇입니까?

 

원하는 타이머를 인터럽트에 연결하고 동일한 ISR을 할당할 수 있습니다.

 

Q. ESP32 타이머는 어떻게 작동합니까?

 

타이머는 클록 주파수와 프리스케일러 값에 따라 특정 속도로 계산하는 카운터를 사용합니다. 이 카운터는 설정 값에 도달하면 재설정되고 인터럽트를 트리거합니다. 이 카운트 값을 변경하여 타이머 간격을 변경할 수 있습니다.

 

ESP32 타이머 인터럽트 예제 - LED 깜박임

 

이 예제에서는 LED 깜박임 프로그램을 테스트합니다. 하지만 지연을 사용하는 대신 타이머 인터럽트를 사용합니다. 이를 위해 아래 회로도에 표시된 대로 브레드보드에 연결합니다.

 

ESP32 LED 깜박임 회로

 

다음은 회로도에 따라 브레드보드에 연결된 실제 회로입니다.

 

ESP32 타이머 튜토리얼

 

LED의 애노드를 GPIO21에 연결하고 캐소드를 220Ω 저항을 통해 GND에 연결합니다.

 

타이머 인터럽트로 LED를 깜박이는 ESP32 코드

 

전체 코드는 아래와 같습니다. 코드 설명을 이어갑니다.

 

#define LED 21
hw_timer_t *My_timer = NULL;
void IRAM_ATTR onTimer(){
	digitalWrite(LED, !digitalRead(LED));
}
void setup() {
	pinMode(LED, OUTPUT);
	My_timer = timerBegin(0, 80, true);
	timerAttachInterrupt(My_timer, &onTimer, true);
	timerAlarmWrite(My_timer, 1000000, true);
	timerAlarmEnable(My_timer); //Just Enable
}

void loop() {
}

 

 

코드를 다운로드하여 ESP32에 업로드합니다. LED가 1Hz의 속도로 깜박이는 것을 볼 수 있습니다. 코드의 각 부분에 대해 논의해 보겠습니다.

 

#define LED 21
hw_timer_t *My_timer = NULL;

 

 

전역 변수 영역에서 LED 핀을 GPIO21로 정의했습니다. 그런 다음 타이머를 구성하기 위해 hw_timer_t 유형의 My_timer라는 포인터 변수를 만들었습니다.

 

void IRAM_ATTR onTimer(){
digitalWrite(LED, !digitalRead(LED));
}

 

 

그런 다음 타이머 인터럽트에 대한 ISR을 만들었습니다. ISR에서 GPIO21의 상태를 반전하는 함수를 작성했습니다. 이 ISR은 타이머 인터럽트가 발생하면 실행됩니다.

 

void setup() {
pinMode(LED, OUTPUT)
My_timer = timerBegin(0, 80, true);
timerAttachInterrupt(My_timer, &onTimer, true);
timerAlarmWrite(My_timer, 1000000, true);
timerAlarmEnable(My_timer);
}
void loop() {
}

 

그리고 Setup 함수에서 pinMode 매크로의 도움으로 GPIO21을 출력으로 초기화했습니다.

 

My_timer = timerBegin(0, 80, true);

 

타이머를 초기화하기 위해 다음 변수와 함께 timerbegin 함수를 사용합니다. 첫 번째 변수는 사용하려는 타이머의 번호(하드웨어 타이머가 4개이므로 0에서 3까지), 두 번째 변수는 프리스케일러의 값이고 마지막 변수는 카운터가 카운트업(true) 또는 카운트다운(false)해야 하는지를 나타내는 플래그입니다. 이 예에서 우리는 프리스케일러 80과 카운터가 카운트업하는 타이머 0을 사용합니다.

 

timerAttachInterrupt(My_timer, &onTimer, true);

 

타이머를 활성화하기 전에 인터럽트가 생성될 때 실행되는 ISR에 연결해야 합니다. 이는 timerAttachInterrupt 함수를 호출하여 수행됩니다. 이 예에서 우리는 onTimer라는 ISR 함수를 타이머 인터럽트에 연결했습니다.

 

timerAlarmWrite(My_timer, 1000000, true);

 

timerAlarmWrite 함수는 타이머 인터럽트가 생성되어야 하는 카운터 값을 지정하는 데 사용됩니다. 따라서 이 예제에서는 매초 인터럽트를 생성하고자 한다고 가정하고 1000000 마이크로초 값을 전달합니다. 이는 1초와 같습니다. 세 번째 인수의 경우 true 값을 전달하여 카운터가 다시 로드되고 인터럽트가 주기적으로 생성됩니다.

 

timerAlarmEnable(My_timer);

 

마지막으로 timerAlarmEnable 함수를 사용하여 타이머 인터럽트를 활성화합니다.

 

여기까지가 전부입니다. 이 링크를 따라가시면 포스팅 참고문서를 만날 수 있습니다.

 

배움을 멈추지 마세요. 우리가 하고 싶었던 일을 하지 않은 후회의 고통은 도전과 실패로 인한 고통보다 훨씬 큽니다. 

 

읽어주셔서 감사합니다.

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^