PIC16F628A TMR0 block diagram.
Fig. 1 TMR0 block diagram.

Programming PIC16F84A-PIC16f628a Timers by Example

by Lewis Loflin

  
  

A PIC16F84A has one 8-bit hardware timer TMR0 while a PIC16F628A has the same thing plus two additional timers TMR1 (16-bit) and TMR2 which is 8-bit. Here I'm concerned only with TMR0 and its prescaler that divides the clock frequency from 1:2 to 1:256 configured by three bits in the OPTION register shown in Fig. 1. Bit 0 - 5 are used to configure the TMR0 operation.

PIC16F84A Option Register
Fig. 2 Option Register.

In Fig. 1 is the internal block diagram for TMR0. We can select an internal clock source which is crystal frequency divided by 4 or an external clock from RA4. Assuming a 4mHz crystal we can use the 1uS count directly or divide by 8 different values up to 256. After 256 counts TMR0 sets its overflow bit (INTCON bit 2) which is 1 on overflow and 0 otherwise.

This flag must be cleared back to zero (BCF, INTCON, 2) before the timer can be used again. The TMR0 register is in BANK0, 0x01. The precount value must be written to the TMR0 register before clearing the overflow flag and done each time the timer is used.



With 0x00 in the TMR0 register, the prescaler at divide by 256, and a 4mHz clock (1uS per tick) the TMR0 flag will be set after 256 X 256 uSec = 65,536 uSec or 65.536 milli seconds. Let's look at some actual working code. The full code for what follows is F84_TMR0_blink.asm.


SETUP			
	BSF	STATUS,RP0  ;Jump to bank 1 of PIC.
	MOVLW B'10000111' ; TMR0 setup
	MOVWF H'81' ; OPTION_REG Also Page 21 in spec sheet 
		
; Note: Writing to TMR0 when the prescaler is
; assigned to Timer0 will clear the prescaler
; count, but will not change the prescaler
; assignment.

	BCF	STATUS,RP0  ;Jump back to bank 0 of PIC.
	GOTO LOOP ; end setup

LOOP ;Loop starts here !!!
	MOVLW B'00000001'
	XORWF PORTB, F
	CALL  TMR0_DEL 
	GOTO  LOOP

; Timer0 delay routine
 TMR0_DEL 
 	MOVLW D'5' ; value X 0.05 sec. 20 is 1 sec.
 	MOVWF COUNT1
 	MOVLW D'59' ; 196 cycles before overflow
 	MOVWF TMR0  ; loc. 0x01
 	BCF INTCON, T0IF ; clear over flow flag bit 2
 	BTFSS INTCON, 2 ; wait for flag set
 	GOTO $-1
 	DECFSZ COUNT1
 	GOTO $-6
 	RETURN

In SETUP I've set the OPTION_REG in BANK1 for TMR0 internal clock, low-to-high transition, prescaler divide by 256. LOOP uses a XOR command to toggle the state ON-OFF of a LED on PB0 then call TMR0_DEL. In subroutine TMR0_DEL we programmed TMR0 to overflow at 50mSec by storing 59 in the TMR0 register. COUNT1 is loaded with a count X for ever how may 50mSec. we need. 5 * 50mSec. = 250mSec.

Then we clear the TMR0 overflow flag (BCF, INTCON, 2) then wait until it's set again. (BTFSZ, INTCON, 2) It then decrements COUNT1 that when it reaches zero will exit the subroutine.

That's how TMR0 works. We will examine on another page how to use TMR0 interrupts.