Stavo guardando come ottenere delle temporizzazioni esatte su ESP32 (esatte anche al μsec) e mi sono messo a studiare la parte relativa a "Timer Group (TIMG)" dopo di ché, seguendo quanto riportato nel reference delle API, nella sezione "General Purpose Timer (GPTimer)" ho provato a buttare giù un semplice programmino che abilita un gptimer in modalità contatore con riavvio automatico che, alla scadenza di un determinato tempo, genera un "interrupt" ...
Sperando che possa essere utile a tutti, riporto, nel post che segue, il codice funzionante ...
... non è altro che un "blink" ma controllato da un gptimer che usa come clock il clock di sistema "GPTIMER_CLK_SRC_APB" (di solito 80 MHz) ed imposta la risoluzione ad 1 MHz (quindi ad 1 μsec); è configurato per contare fino a 500'000 (quindi 1/2 secondo) generare un interrupt e ripartire automaticamente da 0.
Nella ISR che viene richiamata non faccio altro che invertire una variabile e, quindi, accendere o spegnere un LED.
Ovviamente è uno "scheletro di programma" molto semplice da adattare poi per le proprie esigenze reali ... considerate che quantro trovate al link prima indicato è tutto fatto per un compilatore 'C' e che in 'C++', se non lo si adatta, da errori e quindi ... qui avete già il codice corretto che compila in ambiente Arduino (C++).
I gptimers sono molto flessibili e possono essere programmati in vari modi per risolvere problemi di temporizzazioni che si possono incontrare.
/**
* Macro which can be used to check the error code,
* and terminate the program in case the code is not ESP_OK.
* Prints the error code, error location, and the failed statement to serial output.
*
* Disabled if assertions are disabled.
*/
#ifdef NDEBUG
#define ESP_ERROR_CHECK(x) do { \
esp_err_t err_rc_ = (x); \
(void) sizeof(err_rc_); \
} while(0)
#elif defined(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT)
#define ESP_ERROR_CHECK(x) do { \
esp_err_t err_rc_ = (x); \
if (unlikely(err_rc_ != ESP_OK)) { \
abort(); \
} \
} while(0)
#else
#define ESP_ERROR_CHECK(x) do { \
esp_err_t err_rc_ = (x); \
if (unlikely(err_rc_ != ESP_OK)) { \
_esp_error_check_failed(err_rc_, __FILE__, __LINE__, \
__ASSERT_FUNC, #x); \
} \
} while(0)
#endif
Si, la conoscevo, ma l'ho evitata apposta ... con quella perdi il controllo dato che chiama la abort() e manda in errore il sistema facendolo riavviare ... io volevo mostrare un sistema per avere comunque "il controllo" del codice e poter decidere cosa fare ... che poi io in quell'esempio non faccio nulla è vero, ma, in un'applicazione reale, nel IF si potrebbe decidere di fare altre cose ...