I planned on writing a simple program that would use Timer1 to measure the Pulse of a HC-SR04. I thought it would be simple but I can't get the rising edge (and maybe the falling) edge to work.
Using a logic analyzer and the C0 to C3 outputs to monitor the software path I find at
if ((TIFR1 & (1 << ICF1)) == 1); digitalWrite(C0,1); ICF1 is already high.
So my question is; can the capture function of Timer1 be used without an interrupt? Or am I missing something else.
If you are not using the interrupt, you have to manually reset the ICF1 bit of TIFR1 after use by writing 1 to it.
TIFR1
Bit 5 – ICF1: Timer/Counter1, Input Capture Flag
This flag is set when a capture event occurs on the ICP1 pin. When the Input Capture Register (ICR1) is set by
the WGM13:0 to be used as the TOP value, the ICF1 Flag is set when the counter reaches the TOP value.
ICF1 is automatically cleared when the Input Capture Interrupt Vector is executed. Alternatively, ICF1 can be
cleared by writing a logic one to its bit location
I think I'm confused. Its entirely possible I'm missing something critical and just haven't been able to see it.
Bit 5 - ICF1: Timer/Counter1, Input Capture Flag.
This flag is set when a capture event occurs on the ICP1 pin.
I was working under the assumption that I would clear the ICF1 bit, then when a edge (rising or falling depending on the ICES1 bit, the timer count TCNT1 would be copied to OCR1 register.
In the code I posted, I'm using C0 to C3 outputs for debug purposes.
In my test code loop:
I reset C0 to C3 to 0
clear the TCNT1
Set the capture for the rising edge
Reset the whole TIFR1 register
Generate a trigger pulse
test the ICF1 bit, finding it Set then set Port C0 output to High.
The logic trace indicates that the C0 output goes high 4.6µs after the pulse ends suggesting the ICF1 bit is already set making the processor think a rising edge has occurred on the Echo (which it hasn't).
I was working under the assumption that I would clear the ICF1 bit, then when a edge (rising or falling depending on the ICES1 bit, the timer count TCNT1 would be copied to OCR1 register.
On a capture event, the TCNT1 value is written to ICR1.
From the data sheet
When a change of the logic level (an event) occurs on the Input Capture pin (ICP1), or alternatively on the
Analog Comparator output (ACO), and this change confirms to the setting of the edge detector, a capture
will be triggered: the 16-bit value of the counter (TCNT1) is written to the Input Capture Register (ICR1).
The Input Capture Flag (ICF) is set at the same system clock cycle as the TCNT1 value is copied into the
ICR1 Register. If enabled (TIMSK1.ICIE=1), the Input Capture Flag generates an Input Capture interrupt.
The ICF1 Flag is automatically cleared when the interrupt is executed. Alternatively the ICF Flag can be
cleared by software by writing '1' to its I/O bit location.
My earlier posting used an input capture interrupt, and I now realize that you are trying to do this without the interrupt but by monitoring the flag. I apologize for my misunderstanding.
The logic trace indicates that the C0 output goes high 4.6µs after the pulse ends suggesting the ICF1 bit is already set making the processor think a rising edge has occurred on the Echo (which it hasn't).
if ((TIFR1 & (1 << ICF1)) == 1); digitalWrite(C0,1); ICF1 is already high.
The semicolon after the conditional is wrong, and the digitalWrite() happens without the flag set. The 4.6 us is correct for the time to digitalWrite() a pin HIGH.
I think to capture the lead edge after the trigger you want something like
while(ICF1==0){};//wait here
digitalWrite(CO,1);//mark lead edge
//clear flag by writing 1 to the register
//reset edge select
With a prescale of 1, the 16-bit counter is only good for 4095 microseconds or about 70 cm. I'd recommend using a prescale of 8 to get a max distance of 560 cm (5.6 meters).