It is all in the phoenix code… Depending on which version and processors it uses different timers… From the version I uploaded today for serial communications…
some defines to use…
;[TIMING]
lTimerCnt var LONG ; used now also in timing of how long since we received a message
lCurrentTime var long
lTimerStart var long ;Start time of the calculation cycles
lTimerEnd var long ;End time of the calculation cycles
CycleTime var byte ;Total Cycle time
You need to define the interrupts you are using…
[code];[TIMER INTERRUPT INIT]
#ifdef BASICATOMPRO28
TIMERINT con TIMERAINT
ONASMINTERRUPT TIMERAINT, HANDLE_TIMERA_ASM
#else
TIMERINT con TIMERB1INT
ONASMINTERRUPT TIMERB1INT, HANDLE_TIMERB1_ASM
#endif
[/code]
You need to initialize the timer code…
[code];Timer
Then define the timer interrupt code as well as a helper function to get the time…
[code];==============================================================================
;[Handle_Timer_asm] - Handle timer A overflow in assembly language. Currently only
;used for timings for debugging the speed of the code
;Now used to time how long since we received a message from the remote.
;this is important when we are in the NEW message mode, as we could be hung
;out with the robot walking and no new commands coming in.
;==============================================================================
#ifdef BASICATOMPRO28
BEGINASMSUB
HANDLE_TIMERA_ASM
push.l er1 ; first save away ER1 as we will mess with it.
bclr #6,@IRR1:8 ; clear the corresponding bit in the interrupt pending mask
mov.l @LTIMERCNT:16,er1 ; Add 256 to our counter
add.l #256,er1
mov.l er1, @LTIMERCNT:16
pop.l er1
rte
ENDASMSUB
#else
BEGINASMSUB
HANDLE_TIMERB1_ASM
push.l er1 ; first save away ER1 as we will mess with it.
bclr #5,@IRR2:8 ; clear the corresponding bit in the interrupt pending mask
mov.l @LTIMERCNT:16,er1 ; Add 256 to our counter
add.l #256,er1
mov.l er1, @LTIMERCNT:16
pop.l er1
rte
ENDASMSUB
#endif
return ; Put a basic statement before…
;==============================================================================
;[GetCurrentTime] - Gets the Timer value from our overflow counter as well as the TCA counter. It
; makes sure of consistency. That is it is very possible that
; after we grabbed the timers value it overflows, before we grab the other part
; so we check to make sure it is correct and if necessary regrab things.
;==============================================================================
GetCurrentTime:
#ifdef BASICATOMPRO28
lCurrentTime = lTimerCnt + TCA
#else
lCurrentTime = lTimerCnt + TCB1
#endif
; handle wrap
if lTimerCnt <> (lCurrentTime & 0xffffff00) then
#ifdef BASICATOMPRO28
lCurrentTime = lTimerCnt + TCA
#else
lCurrentTime = lTimerCnt + TCB1
#endif
endif
return lCurrentTime
[/code]
lTimerCnt = 0
#ifdef BASICATOMPRO28
WTIMERTICSPERMSMUL con 64 ; BAP28 is 16mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 125 ;
TMA = 0 ; clock / 8192 ; Low resolution clock - used for timeouts…
#else
WTIMERTICSPERMSMUL con 256 ; Arc32 is 20mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 625 ;
TMB1 = 0 ; clock / 8192 ; Low resolution clock - used for timeouts…
#endif
ENABLE TIMERINT
ENABLE
[/code]
How to time something…
; get the start time...
'Start time
GOSUB GetCurrentTime], lTimerStart
... do whatever you wish to time...
; Get the end time
Gosub GetCurrentTime], lTimerEnd
; compute Delta time in Miliseconds...
CycleTime = ((lTimerEnd-lTimerStart) * WTIMERTICSPERMSMUL) / WTIMERTICSPERMSDIV
This is setup to use TimerA on Bap28 and timerB1 on Bap40 and Arc32. It initializes the timer to say only increment every 8192 clocks, size these timers are 8 bit timers that will overflow every 8192*256=2,097,152 clocks. So on Arc32 you will get 20000000/2,097,152 or about 9.5 times per second…
=======================================================================================================
Option 2:
So if all you wish to do is time a specific thing and it will complete in under 1/9.5 seconds and this resolution is sufficient for you than all of this could be overkill. That is you don’t need the interrupt… You could get away with simply using the timer without an interrupt. That is for Arc32, you could simply initialize the timer somewhere at the start…
TMB1 = 0 ; clock / 8192
Then at the start of the code you wish to time simply set the counter associated with the timer to zero
TCB1 = 0
Do your stuff and then at the end save away the timer and convert to ms…
CycleTime = (TCB1 * WTIMERTICSPERMSMUL) / WTIMERTICSPERMSDIV
==========================================================================
Option 3:
Personally if I need this for timings that are not needed for the program itself (like timings for the servos or error out if I don’t see anything on an XBee for a timeout period…) I cheat.
I find an unused IO pin on my board (example P4). At the start of the code I wish to time, I do a: high P4 and the end of the code I wish to time I do a low P4. I then hook up my logic analyzer and record the time. When I move the mouse inside the pulse shown in the analyzer software it will give me the time… But that is cheating!
Sorry for the long winded three different ways answer.
Kurt