Ciò influirebbe sul codice all'interno del ciclo principale che si basa sulla funzione millis () poiché viene spesa una quantità significativa di tempo per elaborare gli ISR?
Per fare una cifra it for you ...
Frequenza del timer 0 overflow ISR che viene chiamato
Viene utilizzato il codice chiamato dal (predefinito) Timer 0 overflow interrupt vector (TIM0_OVF_vect) di millis
e micros
per restituire i risultati. Il suo scopo è contare gli overflow del Timer 0.
Per ottenere risultati accurati, questo ISR non deve perdere un overflow. Il timer è configurato per spuntare ogni 4 µs su un sistema a 16 MHz (a causa del prescaler di 64: 64 * 62,5 ns = 4000 ns
) e overflow ogni 1.024 ms (1024 µs) - perché va in overflow dopo 256 tick ( 4 µs * 256 = 1024 µs
).
Poiché c'è un solo flag di overflow, se l'ISR perde un overflow, quindi sia millisecondi che micro usciranno di 1.024 ms (o più, se manca più overflow).
Per essere certi di catturare tale overflow, l'ISR deve quindi essere chiamato all'interno 1.024 ms (probabilmente leggermente inferiore a causa del tempo impiegato per inserire l'ISR, quindi diciamo: 1 ms).
Priorità interrupt
Su Atmega328P (come usato in Arduino Uno) queste sono le priorità del vettore di interrupt:
1 Reset 2 Richiesta di interruzione esterna 0 (pin D2) (INT0_vect) 3 Richiesta di interruzione esterna 1 (pin D3) (INT1_vect) 4 Cambio pin Richiesta di interrupt 0 (pin da D8 a D13) (PCINT0_vect) 5 Pin Change Inte richiesta interrotta 1 (pin da A0 ad A5) (PCINT1_vect) 6 Pin Change Interrupt Request 2 (pin da D0 a D7) (PCINT2_vect) 7 Watchdog Time-out Interrupt (WDT_vect) 8 Timer / Counter2 Compare Match A (TIMER2_COMPA_vect) 9 Timer / Counter2 Confronta partita B (TIMER2_COMPB_vect) 10 Overflow timer / contatore2 (TIMER2_OVF_vect)
11 Evento acquisizione timer / contatore1 (TIMER1_CAPT_vect) 12 Confronto timer / contatore1 Match A (TIMER1_COMPA_vect) 13 Confronto timer / contatore1 Match B (TIMER1_COMPB_vect) 14 Overflow timer / contatore1 (TIMER1_OVF_vect) 15 Confronto timer / contatore0 Match A (TIMER0_COMPA_vect) Counter0 Compare Match B (TIMER0_COMPB_vect) 17 Timer / Counter0 Overflow (TIMER0_OVF_vect) 18 SPI Serial Transfer Complete (SPI_STC_vect) 19 USART Rx Complete (USART_RX_vect) 20 USART, Data Register vuoto (USART_UDRE_vect) 21 USART, Tx Complete_vect (USART 22TX Conversion) Completo (ADC_vect) 23 EEPROM pronto (EE_READY_vect) 24 Comparatore analogico (ANALOG_COMP_vect) 25 Interfaccia seriale a 2 fili (I2C) (TWI_vect) 26 Store Program Memory Ready (SPM_READY_vect)
Puoi vedere da quell'elenco che TIMER0_OVF_vect è il numero 17 in quell'elenco, quindi qualsiasi interrupt di priorità precedente avrebbe la precedenza, ad esempio interrupt esterni , interrompe il cambio pin, gli altri timer (ma non SPI / Serial / ADC / I2C).
Se un overflow fosse appena avvenuto , avresti praticamente 2 ms di grazia ( perché hai 1 ms prima del successivo e poi un altro 1 ms prima di doverlo notare). Tuttavia, se l'overflow sta per verificarsi , hai solo il periodo di grazia di 1 ms.
Lo dico perché se hai un evento di interrupt esterno 0 (INT0_vect) e l'ISR richiede 500 µs, quindi l'interrupt esterno 1 evento (INT1_vect) durante quel periodo (quindi verrà servito un altro ISR), quindi l'interrupt del timer potrebbe essere bloccato per un po '.
Ecco perché tutti gli ISR dovrebbero essere brevi. Non è abbastanza buono che alcuni di loro lo siano.
Riattivazione degli interrupt
Raccomando vivamente di contro questo. Le librerie non sono progettate per essere rientranti e una volta che inizi ad abilitare gli interrupt in un ISR potresti scoprire che essa stessa viene richiamata di nuovo quando è a metà della chiamata per la prima volta. Si può anche plausibilmente interrompere una funzione di libreria (es. Memcpy) che non è stata progettata per essa.
E, naturalmente, se stai riattivando gli interrupt all'interno di un ISR perché l'ISR richiede molto tempo: beh, questa è la situazione esatta in cui potresti attivare questo re -entrancy.
Ulteriori informazioni: