Electronics > Microcontrollers

AVR: Creating a 24-bit Input Capture Timer

(1/5) > >>

ledtester:
I have a some questions about the correct way to create a 24-bit input capture timer on an 8-bit AVR such as the atmega328.

First, of course, you have to extend TIMER1 by keeping track of overflows. But what's the right way to avoid race conditions between the TIMER1 overflow interrupt and the input capture interrupt? Does this code do the job? Assume that TIMER1 is running in "Normal" mode (mode 0).


--- Code: ---volatile uint8_t overflows;

ISR(TIMER1_OVF_vect) {
    overflows++;
}

ISR(TIMER1_CAPT_vect) {
    uint16_t t = ICR1;
    uint32_t when = (overflows << 16) | t;
    if (TIFR1 & 0x01) {    // check if TOV1 is set
        when += 0x10000;
    }
    // ... do something with when ...
}

--- End code ---

I couldn't find anything the scheduling or priorities of interrupts, so it seems that the capture interrupt routine needs to check the TOV1 flag. Is that right?

Also, I have a question about app note AVR130:

https://ww1.microchip.com/downloads/en/Appnotes/Atmel-2505-Setup-and-Use-of-AVR-Timers_ApplicationNote_AVR130.pdf

At the top of page 14 it states about the input capture interrupt:


--- Quote ---Note:  This implementation has one disadvantage: A timer overflow is not detected. Thus, if the duty
cycle of the wave has a longer period than what can be covered the 16-bit counter, an overflow will
happen before the next edge occurs. A global variable which is set in a timer overflow ISR can be used to
sense whether a timer overflow has happened before the capture is performed. If this variable is set, then
the effective capture value will be (0xFFFF + contents of ICR1).

--- End quote ---

Why do they say to add 0xFFFF instead of 0x10000?

Kleinstein:
Extending the resolution of the timer is a bit tricky with the race condition. AFAIR the ICP interrupts has the higher priority than the overflow - it is the sequence of the interrupt vectors. The point here that the priority is in effect when the interrupt is actually served, not when the interrups actually happend. The old AVR studio simulator (version 1, before about 2005) actually had this wrong, but with the nwer one is was corrected.


Here is a German langish side that shows a solution for extending the resolution:
https://rn-wissen.de/wiki/index.php/Timer/Counter_(Avr)#Input_Capture

ledtester:

--- Quote from: Kleinstein on September 28, 2022, 04:28:19 pm ---Here is a German langish side that shows a solution for extending the resolution:
https://rn-wissen.de/wiki/index.php/Timer/Counter_(Avr)#Input_Capture

--- End quote ---

To summarize this solution, to handle the situation where the input capture happens before the timer overflow but the input capture ISR is not called until after the overflow, check the value of the ICR register. If it is >= 0x8000 then assume the input capture happened before the overflow and otherwise assume it happened after.

As code:


--- Code: ---volatile uint8_t overflows;

ISR(TIMER1_OVF_vect) {
    overflows++;
}

ISR(TIMER1_CAPT_vect) {
    uint16_t t = ICR1;
    uint32_t when = (overflows << 16) | t;
    if ((TIFR1 & 0x01) && (t < 0x8000)) {    // check if TOV1 is set
        when += 0x10000;
    }
    // ... do something with when ...
}

--- End code ---

The code on the rn-wissen.de site has an optimized version of this logic.

ozcar:

--- Quote from: ledtester on September 28, 2022, 03:49:49 pm ---First, of course, you have to extend TIMER1 by keeping track of overflows.

--- End quote ---

Do you? My immediate idea would be to cascade two timers and wire and set them up to capture the same event. But, I have not thought this through, let alone tried it. Maybe that just shifts the problem somewhere else.

Edit, well, maybe you do -  should have thought to RTFM first. Looks like ATMEGA328 has only one input-capture capable timer. I probably had in mind ATMEGA32U4, which has an extra timer.

magic:
If the captured signal is not synchronous with the MCU clock there is no guarantee that two I/O pins will pick it up in the same cycle. Perhaps you could figure out some way of cleaning it up in software.

It might be doable using the events system of more modern AVRs (particularly, a GPIO triggered synchronous event delivered to both timers).

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version