|
DAN122
Dios Timer Primer
By Michael
Simpson
Timers can be very
useful. You can use them to time events or to create intervals. In this application note I'm going to take you through the
various ways the Dios can utilize one of its 4 hardware timers. The
examples use Timer 0 but they should apply to all the timers with minor
variations.
Timer 0 can be used as
both a counter and a timer. In this case we will be using it as a timer.
Even so there is not much difference between the two. It all has to do
with the source that clicks away at the timer. When used as a counter you provide
the source of high/low transitions to port 17. When used as a timer the source is
the system clock. Each tick is equal to 1 nano second in the Dios.
How does a timer work
Each timer has an internal
counter. Some are 8 bit some are 16 bit. Some can be both.
When a timer is enabled the counter starts ticking based on the source.
When the counter overflows (goes from 65535 to 0 for 16 bit) (255 to 0 for 8
bit) it generates an interrupt. In the Interrupt handler we can do
things like set other counters or IO ports.
An interesting point is
that we can pre set the Timer counter with a value so it does not have to go
through its complete cycle. In this way we can control the timing very
closely.
Timers don't have to
generate IRQ's you can start a timer then read it at any time. I
will show you an example of this later.
Registers
Since the Dios is build on
the 18Fxxx architecture we will use the 18Fxxx registers to set up the timer.
Lets take a look at each one
TCON0
This register sets the
specifics for the timer.
Bits 0-2 set up the
presale value. What is a presale? The timers are very fast.
Timer 0 increments a count once each nano second. So lets say the
you need to time a longer event. We use a prescale. A prescal of
1:2 will yield 1/2 the counts so we need to multiply the result by 2 to get
the actual number of nano seconds elapsed.
000 1:2
001 1:4
010 1:8
011 1:16
100 1:32
101 1:64
110 1:128
111 1:256
Bit 3 Turns on or
off the prescale value completely. If set to 0 then a reading of 1:1
will result. IF set to 1 then the bits 0-2 are used to set the prescale.
Bit 4 Sets the
source edge select. 1=increment on high to low. 0=increment on low
to high
Bit 5 Sets the
source of the pin counter. 0=Use internal clock (timer). 1=Use
transition of Port 17 (counter)
Bit 6 Sets 8 bit or
16 bit operation. 0=16 bit operation. 1=8 bit operation
Bit 7 Turns the
timer on and off. 0=off 1=on
TMR0L and TMR0H
These registers contain
the actual value of the timers counter. When writing to them
always write to TMR0H first. When reading always read from TMR0L
first.
INTCON
Only a couple of these
bits are used for Timer 0.
Bit 5 This bit
enables timer 0 to generate an interrupt each time it over flows. 0=no
interrupt 1=interrupt
Bit 7 This bit
turns on or off all interrupts. 0=all off 1=all on
Ok that's enough gobly
gook. Lets get to some program examples.
Example 1
This first program will
demonstrate the use of a non IRQ based timer. We start the timer then
take readings by calling the readtimer function. Note that I reset
the timer after each call my setting the TMR0L and TMR0H to 0. Also no
prescale has been set so the returned value is in actual nano seconds
I can see the starttimer
and readtimer functions making there way into a library.
Program 1
download it here
func main()
dim retvalue
starttimer(0)
pauseus 500
retvalue = readtimer()
print "Pause took ",retvalue,"ns"
retvalue = readtimer()
print "print took ",retvalue,"ns"
endfunc
func starttimer()
'Setup timer 0
T0CON = 0
T0CON.bit(3)= 1 'No prescale' Fastest operation
'When writing to the timer register alwasy write the high byte first
TMR0H=0
TMR0L=0
T0CON.bit(7) = 1 'Turn timer on
endfunc
func readtimer()
dim timervalue
'When reading timer register always read the low byte first
timervalue.byte(0) = TMR0L
timervalue.byte(1) = TMR0H
'Resset the timer
TMR0H=0
TMR0L=0
exit timervalue
endfunc
Example 2
In this program I enhanced the
starttimer0 and readtimer0 functions. You can now set the speed
of the timer.
starttimer0(speed)
This function starts timer 0. You
supply an optional argument to set the speed that the timer operates.
speed: Optional
0 1:1 default
1 1:2
2 1:4
3 1:8
4 1:16
5 1:32
6 1:64
7 1:128
8 1:256
readtimer0(reset)
Returns the timer 0 counter.
0-65535
reset
0: Dont reset. default
1: reset counter
stoptimer0()
Turns timer0 off
Program 2
download it here
func main()
dim retvalue
starttimer0(0)
pauseus 500
retvalue = readtimer0(1)
print "Pause took ",retvalue,"ns"
retvalue = readtimer0(1)
print "print took ",retvalue,"ns"
endfunc
func starttimer0(speed)
if OPP8 = 0 then
speed = 0
endif
branch
speed,speed0,speed1,speed2,speed3,speed4,speed5,speed6,speed7,speed8
'No prescale Fastest operation
'1:1
speed0:
T0CON = 0
T0CON.bit(3)= 1 'No prescale
goto cont
'1:2
speed1:
T0CON = 0
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:4
speed2:
T0CON = 1
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:8
speed3:
T0CON = 2
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:16
speed4:
T0CON = 3
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:32
speed5:
T0CON = 4
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:64
speed6:
T0CON = 5
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:128
speed7:
T0CON = 6
T0CON.bit(3)= 0 'Use Prescale
goto cont
'1:256
speed8:
T0CON = 7
T0CON.bit(3)= 0 'Use Prescale
goto cont
cont:
'When writing to the timer register alwasy write the high byte first
TMR0H=0
TMR0L=0
T0CON.bit(7) = 1 'Turn timer on
endfunc
'Pass 1 if you want to reset counter to 0
func readtimer0(reset)
dim timervalue
if OPP8 = 0 then
reset = 0
endif
'When reading timer register always read the low byte first
timervalue.byte(0) = TMR0L
timervalue.byte(1) = TMR0H
if reset = 1 then
TMR0H=0
TMR0L=0
endif
exit timervalue
endfunc
func stoptimer0()
T0CON.bit(7) = 0 'Turn timer off
endfunc
Example 3
In this example we are going to set
up a software IRQ handler. Software IRQ handlers are
flaged to run after a hardware IRQ has fired on the next Dios Command Cycle.
To set up a software IRQ we use the
onirq command.
Program 3
download it here
func main()
global counter
dim x
clear
setTMR0reg() 'Go set up the hardware registers for Timer 0
onirq TMR0,timerfunc 'Here is where we tell it which software
function to call
loop:
print counter
for x = 1 to 5000
pauseus 10
next
goto loop
endfunc
'--------------------------------------------
irqfunc timerfunc()
counter = counter + 1
exitirq TMR0
endirq
'---------------------------------------------
func setTMR0reg()
'Setup timer 0
T0CON = 3 'Set the timer0 prescale to 1:16
T0CON.bit(3) = 0 'Make sure you use prescale
T0CON.bit(7) = 1 'Turn timer on
'IRQ stuff
INTCON.bit(5) = 1 'Enable Timer 0 IRQ
INTCON.bit(7) = 1 'Enable global interupts
endfunc
Example 4
In this example we made the IRQ a bit
more useful. We took the basic counter an had it increment the
variables sec,min and hours. This allowed us to create a clock that
can me used for short intervals. You will have to tweek the counter a
bit to make it more accurate.
Program 4
download it here
func main()
global counter as integer
global sec as integer
global min as integer
global hour as integer
dim x
clear
setTMR0reg() 'Go set up the hardware registers for Timer 0
onirq TMR0,timerfunc 'Here is where we tell it which software
function
decmask %10000011 'Set display mask to 2 digit
loop:
print hour,":",min,":",sec
for x = 1 to 5000
pauseus 10
next
goto loop
endfunc
irqfunc timerfunc()
counter = counter + 1
if counter = 10 then
counter = 0
sec = sec + 1
if sec = 60 then
sec = 0
min = min + 1
if min = 60 then
min = 0
hour = hour + 1
endif
endif
endif
exitirq TMR0
endirq
func setTMR0reg()
'Setup timer 0
T0CON = 3 'Set the timer0 prescale to 1:16
T0CON.bit(3) = 0 'Make sure you use prescale
T0CON.bit(7) = 1 'Turn timer on
'IRQ stuff
INTCON.bit(5) = 1 'Enable Timer 0 IRQ
INTCON.bit(7) = 1 'Enable global interupts
endfunc
Example 5
One problem with software IRQ
handlers that if extream accuracy is needed they can be delayed from
opperating while certain commands are run. For instance if you use a
pause 5000 command the software IRQ will not fire for 5 seconds.
One solution is to break the pause 5000 command down with multiple smaller
pause commands.
However you may want to create a
hardware IRQ handler. Hardware handlers must be written in assembly so
they are not for the faint of heart. It my goal to provide enough
examples the eventually you can just modify one of the handlers already
written.
Hardware handlers are written using
the startirqasm command.
Note on hardware handlers.
It is possible to steal every cycle away from the main program if events are
happing faster than the handler can process them.
Program 5
download it here
func main()
global counter as integer
global sec as integer
global min as integer
global hour as integer
dim x
clear
'Set the timer
hour = 5
min = 50
setTMR0reg() 'Go set up the hardware registers for Timer 0
decmask %10000011
loop:
print hour,":",min,":",sec
pause 500
goto loop
endfunc
func setTMR0reg()
'Setup timer 0
T0CON = 3 'Set the timer0 prescale to 1:16
T0CON.bit(3) = 0 'Make sure you use prescale
T0CON.bit(7) = 1 'Turn timer on
'IRQ stuff
INTCON.bit(5) = 1 'Enable Timer 0 IRQ
INTCON.bit(7) = 1 'Enable global interupts
endfunc
'Can be placed outside functions
'---------------------------------------------------
'IRQ handler for INT0 IRQ
'---------------------------------------------------
startirqasm TMR0
movlb .2 ;We need this to access global variables
;======================================
incf G_counterl,f
;If counter < 10 then just exit
movlw .10
subwf G_counterl,w
btfss STATUS,Z
goto exithandler
clrf G_counterl
;======================================
incf G_secl,f
;If sec < 60 just exit
movlw .60
subwf G_secl,w
btfss STATUS,Z
goto exithandler
clrf G_secl
;======================================
incf G_minl,f
;If min < 60 just exit
movlw .60
subwf G_minl,w
btfss STATUS,Z
goto exithandler
clrf G_minl
;======================================
infsnz G_hourl,f
incf G_hourh,f
exithandler
;Use this to tweek time
movlw .1 ;Major adjustmets bigger for faster
movwf TMR0H
movlw .0 ;Minor adjustment bigger for faster
movwf TMR0L
endirqasm
Well that's it for the
timer primer. I hoped you learned a little something.
parts list
Breadboard Speaker
DiosPro 40 Pin Chip
Dios Workboard
Deluxe
Easy RS232 Driver
DiosPro 28 Pin Chip
Dios 32 Pin Carrier
(Carrier #1)
9 Pin Cable
Breadboard Regulator
|