Free-run timer TMR0
Timers are usually the most complicated parts of a microcontroller, so it is necessary to set aside more time for
understanding them thoroughly. Through their application it is possible to
establish relations between a real dimension such as "time" and a variable which represents status of a timer within a microcontroller. Physically, timer is a register whose value is continually increasing to 255, and then it starts all over again: 0, 1, 2, 3,
4...255....0,1, 2, 3......etc.
This incrementing is done in the background of everything a microcontroller does. It is up to programmer to think up a way how he will take advantage of this characteristic for his needs. One of the ways is increasing some variable on each timer overflow. If we know how much time a timer needs to make one complete round, then multiplying the value of a variable by that time will yield the total amount of elapsed time.
PIC16F84 has an 8-bit timer. Number of bits determines what value timer counts to before starting to count from zero again. In the case of an 8-bit timer, that number is 256. A simplified scheme of relation between a timer and a prescaler is represented on the previous diagram. Prescaler is a name for the part of a microcontroller which divides oscillator clock before it will reach logic that increases timer status. Number which divides a clock is defined through first three bits in OPTION register. The highest divisor is 256. This actually means that only at every 256th clock, timer
value would increase by one. This provides us with the ability to measure longer timer periods.
After each count up to 255, timer resets its value to zero and starts with a new cycle of counting to 255. During each transition from 255 to zero, T0IF bit in INTCOM register is set. If interrupts are allowed to occur, this can be taken advantage of in generating interrupts and in processing interrupt routine. It is up to programmer to reset T0IF bit in interrupt routine, so that new interrupt, or new overflow could be detected. Beside the internal oscillator clock, timer status can also be increased by the external clock on RA4/TOCKI pin. Choosing one of these two options is done in OPTION register through T0CS bit. If this option of external clock
was selected, it would be possible to define the edge of a signal (rising or falling), on which timer
would increase its value.
In practice, one of the typical example that is solved via external clock and a timer is counting full turns of an
axis of some production machine, like transformer winder for instance. Let's wind four metal screws on the
axis of a winder. These four screws will represent metal convexity. Let's place now the inductive sensor at a distance of 5mm from the head of a screw. Inductive sensor will generate the falling signal every time the head of the screw is parallel with sensor head. Each signal will represent one fourth of a full turn, and the sum of all full turns will be found in TMR0 timer. Program can easily read this data from the timer through a data bus.
The following example illustrates how to initialize timer to signal falling edges from external clock source with a prescaler 1:4. Timer works in
/* SOURCE : WWW.ROMUX.COM
AUTHOR : romux team */
CLRF TMRO ;TMRO=0
CLRF INTCON ;Interrupts and TOIF=0 disallowed
BSF STATUS,RPO ;Bankl because of OPTION_REG
MOVLW B'00110001' ;prescaler 1:4, falling edge selected external
;clock source and pull up ;selected resistors
;on port B activated
MOVWF OPTION_REG ;OPTION_REG <- W
BTFSS INTCON, TOIF ;testing overflow bit
GOTO T0_OVFL ; interrupt has not occured yet, wait
; (Part of the program which processes data regarding a number of turns)
goto TO OVFL ;waiting for new overflow
The same example can be carried out through an interrupt in the following way:
/* SOURCE : WWW.ROMUX.COM
AUTHOR : romux team */
MOVWF W_TEMP ; W_TEMP <- W
SWAPF W_TEMP, F ; Swap them
BANK1 ; Macro for switching to bank1
SWAPF OPTION_REG,W ; W <- OPTION_REG
MOVWF OPTION_TEMP ; OPTION_TEMP <- W
BANKO ; macro for switching to BankO
SWAPF STATUS,W ; W<- STATUS
MOVWF STAT_TEMP ;STAT_TEMP <-W
ENDM ;End of push macro
SWAPF STAT_TEMP,W ; W<- STAT_TEMP
MOVWF STATUS ; STATUS <-W
BANK1 ; Macro for switching to Bankl
SWAPF OPTION_TEMP,W ; W <- OPTION_TEMP
MOVWF OPTION_REG ; OPTION_REG <- W
BANKO ; Macro for switching to BankO
SWAPF W_TEMP,W ; W<- W_TEMP
ENDM ; End of a pop macro
Prescaler can be assigned either timer TMR0 or a watchdog. Watchdog is a mechanism which microcontroller uses to defend itself against programs getting stuck. As with any other electrical circuit, so with a microcontroller too can occur failure, or some work impairment. Unfortunately, microcontroller also has
program where problems can occur as well. When this happens, microcontroller will stop working and will remain in that state until someone resets it. Because of this, watchdog mechanism has been introduced. After a certain period of time, watchdog resets the microcontroller (microcontroller in fact resets itself). Watchdog works on a simple principle: if timer overflow occurs, microcontroller is reset, and it starts executing a program all over again. In this way, reset will occur in case of both correct and incorrect functioning. Next step is preventing reset in case of correct functioning, which is done by writing zero in WDT register (instruction CLRWDT) every time it nears its overflow. Thus program will prevent a reset as long as it's executing correctly. Once it gets stuck, zero will
not be written, overflow of WDT timer and a reset will occur which will bring the microcontroller back to correct functioning again.
Prescaler is accorded to timer TMR0, or to watchdog timer trough PSA bit in OPTION register. By clearing PSA bit, prescaler will be accorded to timer TMR0. When prescaler is accorded to timer TMR0, all instructions of writing to TMR0 register (CLRF TMR0, MOVWF TMR0, BSF TMR0,...) will clear prescaler. When prescaler is assigned to a watchdog timer, only CLRWDT instruction will clear a prescaler
and watchdog timer at the same time . Prescaler change is completely under programmer's control, and can be changed while program is running.
There is only one prescaler and one timer. Depending on the needs, they are
assigned either to timer TMR0 or to a watchdog.
OPTION Control Register
bit 7 RBPU (PORTB Pull-up Enable bit)
This bit turns internal pull-up resistors on port B on or off.
1 = 'pull-up' resistors turned on
0 = 'pull-up' resistors turned off
bit 6 INTEDG (Interrupt Edge Select bit)
If occurrence of interrupts was enabled, this bit would determine at what edge interrupt on RB0/INT pin
1 = rising edge
0 = falling edge
bit 5 T0CS (TMR0 Clock Source Select bit)
This pin enables a free-run timer to increment its value either from an internal oscillator,
i.e. every 1/4 of oscillator clock, or via external impulses on RA4/T0CKI pin.
1 = external impulses
0 = 1/4 internal clock
bit 4 T0SE (TMR0 Source Edge Select bit)
If trigger TMR0 was enabled with impulses from a RA4/T0CKI pin, this bit
would determine whether it would be on the rising or falling edge of a signal.
1 = falling edge
0 = rising edge
bit 3 PSA (Prescaler Assignment bit)
Bit which assigns prescaler between TMR0 and watchdog timer.
1 = prescaler is assigned to watchdog timer.
0 = prescaler is assigned to free timer TMR0
Bit 0:2 PS0, PS1, PS2 (Prescaler Rate Select bit)
In case of 4MHz oscillator, one instruction cycle (4 internal clocks)
Numbers in the following table show the time period in
Ás between incrementing TMR or WDT.