이때 주의할 사항은 PWM과 사용하는 타이머가 겹칠수 있으므로 반드시 실험해서 잘 작동하나 확인해야 함.
좋은 설명 : https://youtu.be/LONGI_JcwEQ
샘플 코드. 출처 : techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
volatile int interruptCounter;
int totalInterruptCounter;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
}
void loop() {
if (interruptCounter > 0) {
portENTER_CRITICAL(&timerMux);
interruptCounter--;
portEXIT_CRITICAL(&timerMux);
totalInterruptCounter++;
Serial.print("An interrupt as occurred. Total number: ");
Serial.println(totalInterruptCounter);
}
}
============================================================================
ESP32 하드웨어 타이머 관련 기본 지식 :
2 그룹의 2개씩의 64비트 하드웨어 타이머 (총 4개, 0 ~ 3)
16 bit prescaler (2 ~ 2^16 사이의 값)
ESP32는 80 Mhz짜리 수정(Crystal)을 사용하므로 (80,000,000 / prescaler) tics / sec 의 속도임.
만약 80으로 나눠주면 80,000,000 / 80 = 1,000,000 tics / sec 이 됨.
아두이노 코드에서 타이머를 사용하려면 다음과 같이 포인터를 만들어 주면 됨.
hw_timer_t * timer = NULL; // 포인터 설정.
그 다음에는 타이머를 지정할 때 3개의 값을 주는데,
1: 타이머 ID (0~3),
2: 나눌 Prescaler 값,
3: true (Rising Edge), false (Falling Edge)
timer = timerBegin(0, 80, true); // 이건 타이머 0를 사용하고, 틱 80,000,000을 80으로 나누고, Rising Edge 사용.
타이머를 Real Time용으로 만들기 위해서 아두이노 IDE에서는 다음과 같은 portMUX_TYPE 오브젝트를 사용함.
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
타이머 함수를 만들어 줄 것.
(*) 타이머 함수를 만들때 주의사항.
1. 코드가 아주 빨리 실행되는 일만 시킬 것. (시리얼 통신같은 무거운 일 시키면 안됨)
2. 각 코드는 고유의 타이머를 연결시킬 것.
3. 타이머 함수에서 함수 외부 코드와 공유할 수 있는 변수는 반드시 (volatile)로 지정할 것.
예 : volatile int t0count;
4. PWM 코드와 사용하는 타이머가 겹치는 지 반드시 확인할 것.
코드 예 :
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
t0count++; // ... critical code executed in the RAM of the ESP32
portEXIT_CRITICAL_ISR(&timerMux);
}
타이머를 활성화(Enable) 시키기 전에 반드시 타이머 함수를 지정하고 연결시킬 것.
timerAttachInterrupt(timer, &onTimer, true);
그 다음에 알람용 (실제 시간마다 실행될 시간)을 지정함.
timerAlarmWrite(timer, 1000000, true); // 이전에 80으로 나눠서 1초에 백만 tic이 돌게 세팅된 상태에
// 백만 tic마다 실행하게 함. 그러므로 이 코드는 1초에 1번 작동함.
마지막에 타이머를 활성화(Enable) 시킴.
timerAlarmEnable(timer);