View Full Version : Pai 32 Bit
I need to read a ground speed sensor to get current speed and cummulate displacement. I want a 32 bit Pulse Accumulator Input and by a periodic time, read new pulse count to extract speed. What is the best way to do this (Isomax v0.6 on Isopod V2)?
RMDumse
09-10-04, 05:16 PM
The timer modules are very flexible.
Without actually writing the program for you, I have been looking at the timers, and here are my suggestions. Set up one timer to count external pin positive edges. Perhaps TMRA0 for instance. Then set another timer in the same group to cascade. TMRA1 for instance. Now that will give you a 32-bit pulse accumulator.
Then set up another timer in the same group to count IP clocks. TMRA2 for instance. Set this one to set its output flag on completion. Make the other two capture their count, and use the secondary input for them to be the pin for this third timer.
Here are my notes about set up of the CNTL and STATUS registers of the three timers. I'm not absolutely certain I've got it right. Perhaps you could try this and report back if it is working as expected.
[CODE]
( TMRA0 - low order for 32 pulse accumulator
( 001 ( COUNT RISING EDGES OF PRIMARY SOURCE
( 0000 ( Counter #0 input pin
( 10 ( SECONDARY COUNT Counter # 2 input
( 0 ( COUNT ONCE - 0 REPEATEDLY
( 0 ( COUNT LENGTH ROLL OVER
( 0 ( DIR COUNT UP
( 0 ( COINIT NO FORCE BY OTHER CHANNELS
( 000 ( OUPUT MODE, Active while counter is active
( CTRL 0010000100000000 - 0010 0001 0000 0000 - 2100
( 00 TCF, TCFIE
( 00 TOF, TOFIE
( 00 IEF, IEFIE
( 0 IPS
( 0 INPUT
( 01 CAPTURE REGISTER OPERATION CAP ON RISING EDGE IF IPS=0
( 0 MASTER
( 0 EEOF
( 0 VAL
( 0 FORCE
( 0 OPS
( 0 OEN
( STATUS 000000001000000 - 0000 0000 0100 0000 - 0040
( TMRA1 - high order for 32 pulse accumulator
( 111 ( CASCASE COUNTER MODE UP/DOWN
( 0100 ( Counter #0 output
( 10 ( SECONDARY COUNT Counter # 2 input
( 0 ( COUNT ONCE - 0 REPEATEDLY
( 0 ( COUNT LENGTH ROLL OVER
( 0 ( DIR COUNT UP
( 0 ( COINIT NO FORCE BY OTHER CHANNELS
( 000 ( OUPUT MODE, Active while counter is active
( CTRL 1110100100000000 - 1110 1001 0000 0000 - E900
( 00 TCF, TCFIE
( 00 TOF, TOFIE
( 00 IEF, IEFIE
( 0 IPS
( 0 INPUT
( 01 CAPTURE REGISTER OPERATION CAP ON RISING EDGE IF IPS=0
( 0 MASTER
( 0 EEOF
( 0 VAL
( 0 FORCE
( 0 OPS
( 0 OEN
( STATUS 000000001000000 - 0000 0000 0100 0000 - 0040
( TMRA2 - period counter
( 001 ( COUNT RISING EDGES OF PRIMARY SOURCE
( 1111 ( PRIMARY COUNT SOURCE IP/128
( 00 ( SECONDARY COUNT Counter # 0 input
( 0 ( COUNT ONCE - 0 REPEATEDLY
( 1 ( COUNT LENGTH COUNT UNTIL COMPARE AND REINITIALIZE
( 0 ( DIR COUNT UP
( 0 ( COINIT NO FORCE BY OTHER CHANNELS
( 010 ( SET OFLAG OUTPUT ON SUCCESSFUL COMPARE
( CTRL 0011111000100010 - 0011 1110 0010 0010 - 3E22
( 00 TCF, TCFIE
( 00 TOF, TOFIE
( 00 IEF, IEFIE
( 0 IPS
( 0 INPUT
( 00 CAPTURE DISABLED
( 0 MASTER
( 0 EEOF
( 0 VAL
( 0 FORCE
( 0 OPS
( 1 OEN
( STATUS 000000001000001 - 0000 0000 0100 0000 - 0041
[\CODE]
It works but..
At the start-up, initialisation is made and counter value is set to zero. When receiving the first pulse, both high and low order words go to 1 ! The high order word works well after this first pulse why?
RMDumse
09-20-04, 05:10 PM
Try initializing the lowest counter to 0001, rather than 0000, and see if that doesn't work better for you.
Bad Bad Bad...
Yes it works when i start from one but see what's append to the high and low order words..
High = 0 Low = 1
pulse counting....
High = 0 Low = 65535
High = 0 Low = 0
High = 1 Low = 1
High = 1 Low = 2
...
The roll over count is not a good reading, i will check it before storing the value. The final result is better than the first one when passing from 1 to 65537!
mckenney
09-21-04, 08:13 PM
If you'll pardon my $0.02, this looks suspiciously like an
atomic-read problem, meaning that the carry from low to
high word happened while you were reading the two halves.
The standard solution is to read one of the words twice, and
re-read the other word if the two readings are different. I don't
know how it looks in Forth, but in C:
t2 = input_high;
do {
t1 = t2;
result_low = input_low;
t2 = input_high;
} while (t1 != t2);
result_high = t2;
To bypass this problem, i reject readings with low order word at zero and use last good reading. It can affect other variables derated from this but i have to live with it, mostly if it stop on a zero ending.
nmitech
09-22-04, 10:55 AM
I am not sure if this might related to your problem. Please see the errata number 1.6 on the 1st page,
http://www.freescale.com/files/dsp/doc/errata/DSP56F805E.pdf
No, I'm in 32 bits pulse reading mode.
The problem is that the carry of the low order word affect the high order word when passing from 0 to 1 against wrap around from ffff to 0 like all the world know!
RMDumse
09-22-04, 06:24 PM
I think I've isolated the problem. You are getting a "double bounce" on the output flag due to not taking care with your compare register. Look at this code:
COLD
HEX
: INIT
2710 D00 ! ( CMP1
3E8 D08 ! ( CMP1
0000 D10 ! ( CMP1
0000 D18 ! ( CMP1
0000 D07 ! ( STATUS
0000 D0F ! ( STATUS
0000 D17 ! ( STATUS
0000 D1F ! ( STATUS
0000 D05 ! ( COUNTER
0000 D0D ! ( COUNTER
0000 D15 ! ( COUNTER
0000 D1D ! ( COUNTER
EC00 0D1E !
EA00 0D16 !
E820 0D0E !
3420 0D06 !
;
: TEST ( Define name of word.
INIT
CR
BEGIN ( Use a nasty PCCloop. okay only because it is in foregnd
D05 @ D0C @ D14 @ D1C @
D. . .
D EMIT ( emit the return, without the linefeed
?TERMINAL ( Look at serial register for
UNTIL ( End of nasty PCCloop with backwards branch
; ( finish definition
DECIMAL
This code is a long chain counter. TMRA0 counts 10,000 to overflow on milliseconds. TMRA1 counts 1000 to overflow on seconds. TMRA2 counts the seconds and overflows cascading into TMRA3. Downloaded like this, when TMRA2 goes from 0000 to 0001, TMRA3 also goes to 0001, and the count is displayed as 65537. However, change only the compare register for TMRA2 to FFFF, and the problem goes away.
COLD
HEX
: INIT
2710 D00 ! ( CMP1
3E8 D08 ! ( CMP1
FFFF D10 ! ( CMP1
0000 D18 ! ( CMP1
0000 D07 ! ( STATUS
0000 D0F ! ( STATUS
0000 D17 ! ( STATUS
0000 D1F ! ( STATUS
0000 D05 ! ( COUNTER
0000 D0D ! ( COUNTER
0000 D15 ! ( COUNTER
0000 D1D ! ( COUNTER
EC00 0D1E !
EA00 0D16 !
E820 0D0E !
3420 0D06 !
;
: TEST ( Define name of word.
INIT
CR
BEGIN ( Use a nasty PCCloop. okay only because it is in foregnd
D05 @ D0C @ D14 @ D1C @
D. . .
D EMIT ( emit the return, without the linefeed
?TERMINAL ( Look at serial register for
UNTIL ( End of nasty PCCloop with backwards branch
; ( finish definition
DECIMAL
vBulletin v3.0.7, Copyright ©2000-2012, Jelsoft Enterprises Ltd.