PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Software-Timer



Netzman
17.09.2009, 23:29
Hallo,

Ich möchte hier meine Software-Timer Library vorstellen, ich verwende sie bei fast allen Projekten, vielleicht kann jemand etwas damit anfangen.

Die Lib verwendet einen HW-Timer und verwaltet bis zu 256 voneinander unabhängige Software-Timer. Die Parameter für den HW-Timer werden aus der gewünschten Timer-Frequenz berechnet.

Der Code ist ansich gut dokumentiert und selbsterklärend:
(tickers.bas)
$nocompile
'################################################# ##############################
'## ##
'## U N I V E R S A L S O F T W A R E T I M E R ##
'## =============================================== ##
'## ##
'## Description: This is an easy-to-use universal software timer library, ##
'## for use with any hardware timer, featuring automatic ##
'## determination of needed timer parameters on precompile, ##
'## up to 256 independant software timers, each can be ##
'## enabled/disabled and an interrupt queue if more than one ##
'## sw interrupt occured at once. ##
'## ##
'## Author: Matthias (at) Braunecker (.at) ##
'## Version: 1.0 Date: July 2009 ##
'## ##
'## Free for personal use, credits and a short mail with your project info ##
'## and/or comments, improvements etc. to this library would be nice. ##
'## ##
'################################################# ##############################

' How to use this (the values are just for example):
' --------------------------------------------------

' Initialisation:
' $crystal = 16000000
' [...] ' your Code
' Const False = 0: Const True = 1 ' for better reading

' Const Ticker_hwtimer = 0 ' Choose which hardware timer to use
' Const Ticker_frequency = 10000 ' set the timer resolution
' Const Tickers = 2 ' # of software timers to use
' $include "tickers.bas"
' Ticker_time(1) = 25 ' Interrupt Ticks to trigger SW-Timer 1
' Ticker_time(2) = 500 ' SW-Timer 2 and so on...
' Ticker_enabled(1) = True ' Enable/Disable SW-Timer
' Ticker_enabled(2) = False
' [...]
' Enable Interrupts

' Main Loop:
' Do
' [...]
' Select Case Ticker_get_interrupt() ' make sure that this function is called at least once per
' hw timer overflow, so don't make the µC hanging around
' Case 1: ' Ticker 1 triggered an interrupt
' [...]
' Case 2: ' Ticker 2 interrupt
' [...]
' End Select
' [...]
' Loop


Declare Function Ticker_get_interrupt() As Byte
Declare Sub Ticker_enable(byval Tickernr As Byte)


'################################################# ##############################
'## T I M E R S E T T I N G S C A L C U L A T I O N ##
'################################################# ##############################
' calculation based on a work by "Walter", MCS Forum, added prescaler calculation
Const Ticker_cyclespertick = _xtal / Ticker_frequency ' clock cycles needed for desired frequency
#if Ticker_hwtimer = 0 ' Set the timer register size
Const Ticker_register = 256
#endif
#if Ticker_hwtimer = 1
Const Ticker_register = 65536
#endif
#if Ticker_hwtimer = 2
Const Ticker_register = 256
#endif

#if(ticker_cyclespertick / 1) < Ticker_register ' calculate the right prescale value
Const Ticker_prescale = 1
#else
#if(ticker_cyclespertick / 8) < Ticker_register
Const Ticker_prescale = 8
#else
#if(ticker_cyclespertick / 64) < Ticker_register
Const Ticker_prescale = 64
#else
#if(ticker_cyclespertick / 256) < Ticker_register
Const Ticker_prescale = 256
#else
#if(ticker_cyclespertick / 1024) < Ticker_register
Const Ticker_prescale = 1024
#endif
#endif
#endif
#endif
#endif

Const Ticker_tickfrequency = _xtal / Ticker_prescale ' frequency of Timer-Ticks
Const Ticker_ticktime = 1 / Ticker_tickfrequency ' time of one Timer-Tick in sec
Const Ticker_desiredtime = 1 / Ticker_frequency ' desired time in sec
Const Ticker_count = Ticker_desiredtime / Ticker_ticktime ' number of Ticks for desired time
Const Ticker_preload = Ticker_register - Ticker_count ' start-value for the timer


'################################################# ##############################
'## V A R I A B L E S ##
'################################################# ##############################
Dim Ticker_counter(tickers) As Word ' tick counter
Dim Ticker_time(tickers) As Word ' desired intervall time
Dim Ticker_interrupt(10) As Byte ' interrupt stack
Dim Ticker_pointer As Byte ' interrupt stack pointer
Dim Ticker_tmp As Byte ' internal temp variable
Dim Ticker_enabled(tickers) As Byte ' enable/disable ticker
Dim Ticker_newtick As Bit ' hw timer interrupt flag


'################################################# ##############################
'## S E T T I N G U P H W - T I M E R ##
'################################################# ##############################
#if Ticker_hwtimer = 0
Ticker_timer Alias Timer0
Config Ticker_timer = Timer , Prescale = Ticker_prescale
On Timer0 Ticker_isr Nosave
Enable Timer0
#endif
#if Ticker_hwtimer = 1
Ticker_timer Alias Timer1
Config Ticker_timer = Timer , Prescale = Ticker_prescale
On Timer1 Ticker_isr Nosave
Enable Timer1
#endif
#if Ticker_hwtimer = 2
Ticker_timer Alias Timer2
Config Ticker_timer = Timer , Prescale = Ticker_prescale
On Timer2 Ticker_isr Nosave
Enable Timer2
#endif

Ticker_timer = Ticker_preload
Goto Ticker_runprog ' don't execute the functions


'################################################# ##############################
'## F U N C T I O N S ##
'################################################# ##############################
Sub Ticker_enable(byval Tickernr As Byte) ' enables and resets a sw-timer
Ticker_enabled(tickernr) = True
Ticker_counter(tickernr) = 0
End Sub

'-------------------------------------------------------------------------------
Function Ticker_get_interrupt() As Byte ' Main function
If Ticker_newtick = True Then ' hw timer interrupt occured
Ticker_newtick = False ' reset the flag
For Ticker_tmp = 1 To Tickers ' check all sw tickers
If Ticker_enabled(ticker_tmp) = 1 Then Incr Ticker_counter(ticker_tmp) ' if ticker enabled, increment tick count
If Ticker_counter(ticker_tmp) = Ticker_time(ticker_tmp) Then ' tick count has reached desired time
Incr Ticker_pointer
Ticker_interrupt(ticker_pointer) = Ticker_tmp ' store the interrupt in queue
Ticker_counter(ticker_tmp) = 0 ' reset ticker counter
End If
Next
End If
If 0 < Ticker_pointer Then ' interrupt is waiting in queue
Ticker_get_interrupt = Ticker_interrupt(ticker_pointer)
Ticker_interrupt(ticker_pointer) = 0 ' interrupt processed, delete it
Decr Ticker_pointer
Else
Ticker_get_interrupt = False ' no interrupt waiting
End If
End Function

'-------------------------------------------------------------------------------
Ticker_isr: ' hw timer interrupt service routine
$asm
push R25
push R24
IN R24, SREG
PUSH R24
$end Asm
Ticker_timer = Ticker_preload ' reset the timer register with calculated preload value
Ticker_newtick = True ' set flag
$asm
pop R24
Out Sreg , R24
POP R24
pop R25
$end Asm
Return

Ticker_runprog:

mfg