What I have found with interrupts, and serout/serin, that if you are doing any speeds > 9600 baud, any interrupt will for sure screw it up, if it happens at the wrong time. Even at 9600 baud it will screw it up from time to time. I have found this with even real simple interrupts.
I am not sure which processor you are using, but if I assume a BAP40/Arc32/Bap64 which runs at 20mhz, I believe your TimerV will overflow about 610 times per second, which is about 6 times faster than you want... You could use TimerB1 and divide the clock by 256 or 512 instead if you wish to reduce this... down some more...
In the phoenix code we don't need a very high resolution for the timer, so I use the TimerA or TimerB1 depending on processor and I do a divide by 8192, so we only need to process about 9.5 interrupts per second. With that it is easy to setup the code to disable the interrupt just before a serout and reenable it after and know I won't lose anything. I also have some simple functions that grab the current clock time and then later grab the clock again and see if the delta exceeds some delta...
Example for Bap28:
Code:
;====================================================================
lTimerCnt var long
;--------------------------------------------------------------------
;[TIMER INTERRUPT INIT]
TIMERINT con TIMERAINT
ONASMINTERRUPT TIMERAINT, HANDLE_TIMERA_ASM
;--------------------------------------------------------------------
;[InitServoDriver] - Initializes the servo driver including the main timer used in the phoenix code
InitTimer:
;Timer
; Timer A init, used for timing of messages and some times for timing code...
TIMERINT con TIMERAINT
WTIMERTICSPERMSMUL con 64 ; BAP28 is 16mhz need a multiplyer and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 125 ;
TMA = 0 ; clock / 8192 ; Low resolution clock - used for timeouts...
ENABLE TIMERINT
return
;==============================================================================
;[Handle_Timer_asm] - Handle timer A overflow in assembly language. Currently only
;used for timings for debuging 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.
;==============================================================================
BEGINASMSUB
HANDLE_TIMERA_ASM
push.l er1 ; first save away ER1 as we will mess with it.
bclr #6,@IRR1:8 ; clear the cooresponding 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
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:
lCurrentTime = lTimerCnt + TCA
; handle wrap
if lTimerCnt <> (lCurrentTime & 0xffffff00) then
lCurrentTime = lTimerCnt + TCA
endif
return lCurrentTime
;-------------------------------------------------------------------------------------
;[ConvertTimeMS]
_ttconv var long
ConvertTimeMS[_ttconv]:
return (_ttconv * WTIMERTICSPERMSMUL)/WTIMERTICSPERMSDIV
Usage is pretty easy:
Code:
'Start time
GOSUB GetCurrentTime[], lTimerStart
...
GOSUB GetCurrentTime[], lTimerEnd
GOSUB ConvertTimeMS[lTimerEnd-lTimerStart], CycleTime
Could simplify this some more... The Bap40/64 versions are about the same, except some of the register names changes...
TCA -> TCB1...
Also the Conversion factor constants change:
Code:
WTIMERTICSPERMSMUL con 256 ; Arc32 is 20mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 625 ;
Hope that helps
Kurt