Assuming you'd like to measure the duty cycle of the input signal applied
one of the capture pins of T0, do the following:
1) setup input pin as capture input and rising edge sensitive
2) provide 4 unsigned int storage namely POSITIVE,NEGATIVE,NEGWIDTH,POSWIDTH
3) in the timer0 interrupt service function check if cap0.x event occured
(this is your pin)
4) check T0CCR relevant bits if it is programmed for rising edge goto 5 else
goto 9
5) store captured value in POSITIVE
6) calculate NEGWIDTH = POSITIVE - NEGATIVE
7) setup T0CCR as falling edge sensitive for the next event (negative edge
will come soon)
8) exit function
9) store captured value in NEGATIVE
10) calculate POSWIDTH = NEGATIVE - POSITIVE
11) setup T0CCR as rising edge sensitive for the next event (positive edge
will come soon)
12) exit function
The very first reading of the above will be spurious as the algorithm
requires 3 edges (positive-negative-positive) to get stabilized. However
this can be avoided with a boolean flag. This flag can be set in the second
positive edge event and the main program can check this flag and ignore the
difference values if it is not set yet.
Also make sure you only have one capture or match interrupt in the timer0 as
some errata causing missed interrupts in the timers exists (at least it
exists in LPC2214 - you may check yours). If such errata exists and you need
multiple captures be handled by timer0, you may lookup the code I have
downloaded last week to resolve the problem.
For the other interrupts causing incorret reading issue, there wont be in
the above algorithm as far as interrupts dont get disabled more than the
time between two edges. If you wish you may enable all the interrupts
assuming you have the enter and exit code of the irq handler modified.
For the dedsired accuracy set you timer0 clock rate accordingly. If you need
0.1% accurate readings timer0 should be set to count at least 1000 pulses
between each event.
The above algorith works and gives very stable readings. You may test it
with a frequency gerenerator output applied to your input pin.
Here is an example code assuming your input is CAP0.2
....
if(T0IR&0x40) { // check if
CAP0.2 interrupt interrupt
T0IR=0x40; // clear
interrupt flag
if(T0CCR & 0x40) { // rising edge
occured
ps.curr.pos_cap=T0CR2; // capture timer
at this positive edge
ps.curr.nw=ps.curr.pos_cap-ps.curr.neg_cap; // calculate
previous negative width
__clrio(T0CCR,0x40);
__setio(T0CCR,0x80); // next int on
negative edge
}
else {
if(T0CCR&0x80) { // rising edge
ps.curr.neg_cap=T0CR2; // capture timer
at this negative edge
ps.curr.pw=ps.curr.neg_cap-ps.curr.pos_cap; // calculate
previous positive width
__clrio(T0CCR,0x80);
__setio(T0CCR,0x40); // next int on
positive edge
}
}
}
...
I hope you will be able to see your readings soon...
Kerem
----- Original Message -----
From: "chazeltopman" <rob@...>
To: <lpc2000@yahoogroups.com>
Sent: Saturday, January 22, 2005 1:05 AM
Subject: [lpc2000] accurate pulse measurements
>
>
> I'm trying to capture the width of a pulse using the capture
> timers on the LPC2106 and getting an accurate reading every
> time has proven difficult. The pulses are 200 to 700
> microseconds long. I thought that I could capture them in
> the following way:
>
> Algorithm 1:
> o set up capture timer channel 0 to interrupt on each edge
> o on interrupt check level to see if high to indicate a
> rising edge
> o if high, remember captured time and wait for falling edge
> o when falling edge occurs subtract rising edge time and
> queue up the length of the pulse
>
> I implemented this algorithm and my numbers vary quite a bit.
> If I scope the signals, they are clean so the variance is not
> due to noise and is due to interrupt collision or a misunderstanding
> of the timer capture. The above algorithm will fail if another
> interrupt occurs preventing the captured count from being read
> before another edge transition occurs. This is probably what is
> happening in my case. So I've been thinking about how else to
> capture the two edges without software getting in the way. The
> only way I can think of is to use two capture inputs and a match
> register.
>
> Algorthm 2:
> o the first capture input captures the time on the rising edge
> o the second capture input captures the time on the falling edge
> o the match register provides a timed interrupt in which at
> least two edges have been captured
>
> In my case I'd set it to be a millisecond since the pulse is
> periodic with about a millisecond period (I'm really measuring the
> duty cycle). Then comparing the rising and falling edge capture
> times, I can deduce whether I've captured the low pulse (falling
> edge before rising edge) or the high pulse (rising edge before
> falling edge) and calculate the high pulse from the captured times.
> Also by taking a group of measurements, I should get some of
> the high pulse and some of the low pulse. Using this info, I
> should be able to deduce the period as well instead of measuring
> that independantly.
>
> While this algorithm seems like it should work, it uses two inputs
> per pulse input. If someone else has a better idea please toss
> it into the arena.
>
> Rob
>
>
>
>
>
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
>Message
Re: [lpc2000] accurate pulse measurements
2005-01-22 by Kerem Or
Attachments
- No local attachments were found for this message.