Vil dette påvirke koden inne i hovedsløyfen som er avhengig av millis () -funksjonen siden det brukes betydelig tid på å behandle ISR-ene?
Å sette en figur på det for deg ...
Frekvens for Timer 0 overløp ISR blir kalt
Koden som kalles av (standard) Timer 0 overløpsavbruddsvektor (TIM0_OVF_vect) brukes av millis
og micros
for å bidra til å returnere resultatene. Hensikten er å telle Timer 0-overløp.
For å få nøyaktige resultater, må denne ISR ikke gå glipp av et overløp. Timeren er konfigurert til å krysse hver 4. µs på et 16 MHz-system (på grunn av prescaler på 64: 64 * 62,5 ns = 4000 ns
) og overflow hver 1.024 ms (1024 µs) - fordi den renner over etter 256 flått ( 4 µs * 256 = 1024 µs
).
Siden det bare er ett overløpsflagg, hvis ISR savner et overløp, så vil både millis og micros være ute med 1.024 ms (eller mer, hvis det går glipp av flere overløp).
For å være sikker på å fange det overløpet, må ISR derfor kalles innen 1.024 ms (sannsynligvis litt mindre på grunn av tiden det tar å gå inn i ISR, så si: 1 ms).
Avbryt prioritet
På Atmega328P (slik som brukt i Arduino Uno) disse er avbruddsvektorprioriteringene:
1 Reset 2 External Interrupt Request 0 (pin D2) (INT0_vect) 3 External Interrupt Request 1 (pin D3) (INT1_vect) 4 Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect) 5 Pin Change Inte rrupt Request 1 (pins A0 to A5) (PCINT1_vect) 6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect) 7 Watchdog Time-out Interrupt (WDT_vect) 8 Timer / Counter2 Compare Match A (TIMER2_COMPA_vect) 9 Timer / Counter2 Sammenlign kamp B (TIMER2_COMPB_vect) 10 Timer / Counter2 Overflow (TIMER2_OVF_vect)
11 Timer / Counter1 Capture Event (TIMER1_CAPT_vect) 12 Timer / Counter1 Sammenlign Match A (TIMER1_COMPA_vect) 13 Timer / Counter1 Sammenlign Match B (TIMER1_COMPB_vect) 14 Timer / Counter1 Overflow (TIMER1_OVF_vect) 15 Timer / Teller_TIMER / Teller0 Counter0 Sammenlign 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 Empty (USART_UDRE_vect) 21 USART, Konvertering_USC Komplett (ADC_vect) 23 EEPROM Ready (EE_READY_vect) 24 Analog Comparator (ANALOG_COMP_vect) 25 2-leder serielt grensesnitt (I2C) (TWI_vect) 26 Lagre programminneklar (SPM_READY_vect)
Du kan se fra den listen at TIMER0_OVF_vect er nummer 17 på den listen, så tidligere prioritetsavbrudd vil ha forrang, for eksempel eksterne avbrudd , pin-endringsavbrudd, de andre tidtakerne (dog ikke SPI / Serial / ADC / I2C).
Hvis et overflyt bare hadde skjedd så ville du ha praktisk talt 2 ms nåde ( fordi du har 1 ms før neste og deretter 1 ms til før du trenger å legge merke til det). Men hvis overløpet er i ferd med å skje så har du bare 1 ms avdragsfri periode.
Jeg nevner dette fordi hvis du har en ekstern interrupt 0-hendelse (INT0_vect) og ISR tar 500 µs, og deretter ekstern avbrudd 1-hendelse (INT1_vect) i løpet av den tiden (slik at en annen ISR vil bli betjent), kan tidsavbruddet bli blokkert en stund.
Det er grunnen til at alle ISR-er bør være korte. Det er ikke bra nok at noen av dem er det.
Gjenaktivering av avbrudd
Jeg anbefaler på det sterkeste mot dette. Bibliotekene er ikke designet for å komme inn igjen, og når du begynner å aktivere avbrudd i en ISR, kan du oppdage at den selv blir ringt igjen når den er halvveis gjennom å bli kalt første gang. Du kan også tenke deg å avbryte en biblioteksfunksjon (f.eks. Memcpy) som ikke var designet for den.
Og selvfølgelig, hvis du aktiverer avbrudd på nytt i en ISR fordi ISR tar lang tid: vel, det er den nøyaktige situasjonen når du kan utløse denne re -entrancy.
Mer informasjon: