ATmega328P Data Sheet - https://content.arduino.cc/assets/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
Using Timer1
static uint8_t saveTCCR1A, saveTCCR1B; static inline void capture_init(void) { // save existing timer settings saveTCCR1A = TCCR1A; saveTCCR1B = TCCR1B; // initialize timer1 TCCR1B = 0; TCCR1A = 0; //Initialize counter value to 0 TCNT1 = 0; //Set Timer/Counter1 Interrupt Flag Register //ICF1: Timer/Counter1, Input Capture Flag //TOV1: Timer/Counter1, Overflow Flag TIFR1 = (1<<ICF1) | (1<<TOV1); //Set Interrupt Mask Register // ICIE1: Timer/Counter1, Input Capture Interrupt Enable // TOIE1: Timer/Counter1 Overflow Interrupt Enable TIMSK1 = (1<<ICIE1) | (1<<TOIE1);} } static inline void capture_start(void) { //Set Timer/Counter1 Control Register B // ICNC1: Input Capture Noise Canceler // ICES1: Input Capture Edge Select // CS10: Clock Select - clkIo/1 (no prescaling) TCCR1B = (1<<ICNC1) | (1<<ICES1) | (1<<CS10); } static inline uint16_t capture_read(void) { //input capture register return ICR1; } static inline uint8_t capture_overflow(void) { //Set Timer/Counter1 Interrupt Flag Register // TOV1: Timer/Counter1, Overflow Flag return TIFR1 & (1<<TOV1); } static inline void capture_overflow_reset(void) { //Set Timer/Counter1 Interrupt Flag Register // TOV1: Timer/Counter1, Overflow Flag TIFR1 = (1<<TOV1); } static inline void capture_shutdown(void) { TCCR1B = 0; TIMSK1 = 0; //Restore old timers TCCR1A = saveTCCR1A; TCCR1B = saveTCCR1B; } #define TIMER_OVERFLOW_VECTOR TIMER1_OVF_vect #define TIMER_CAPTURE_VECTOR TIMER1_CAPT_vect #define FREQMEASURE_BUFFER_LEN 12 static volatile uint32_t buffer_value[FREQMEASURE_BUFFER_LEN]; static volatile uint8_t buffer_head; static volatile uint8_t buffer_tail; static uint16_t capture_msw; static uint32_t capture_previous; ISR(TIMER_OVERFLOW_VECTOR) { capture_msw++; } ISR(TIMER_CAPTURE_VECTOR) { uint16_t capture_lsw; uint32_t capture, period; uint8_t i; // get the timer capture capture_lsw = capture_read(); // Handle the case where but capture and overflow interrupts were pending // (eg, interrupts were disabled for a while), or where the overflow occurred // while this ISR was starting up. However, if we read a 16 bit number that // is very close to overflow, then ignore any overflow since it probably // just happened. if (capture_overflow() && capture_lsw < 0xFF00) { capture_overflow_reset(); capture_msw++; } // compute the waveform period capture = ((uint32_t)capture_msw << 16) | capture_lsw; period = capture - capture_previous; capture_previous = capture; // store it into the buffer i = buffer_head + 1; if (i >= FREQMEASURE_BUFFER_LEN) i = 0; if (i != buffer_tail) { buffer_value[i] = period; buffer_head = i; } }