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.

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.


;========================================
;	CLOCK: External 4MHz (instruction execution time: 1usec)
;	This is a basic start template for PIC16F84A
;	Includes delay routines 
;	Program name: TMR0 Delay Non-Interrupt
;	Date: 6-16-2024
;	Author: Lewis Loflin
;	MPLAB v8.92	compiles to 29 bytes.
;========================================

	list      p=16F84A ; list directive to define processor
	#include <p16F84A.inc> ; processor specific variable definitions
	errorlevel  -302 ; Ignore error message when storing to Bank 1.
        
  	__CONFIG  _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC 
  
;=========================================

;*****[ Data Storage Reg's ]*****
            CBLOCK  0x0C ; Assign each reg. from Bank 0 RAM area.
            CNT1
            CNT2
			CNT3
			CNT4
            TEMP1
            TEMP2
            ENDC  ; Conclude Bank 0 RAM assignments.

;**********************************************************************
	ORG     0x000             ; processor reset vector
	goto    setup              ; go to beginning of program
	
	ORG     0x004             ; interrupt vector location
	retfie                    ; return from interrupt

;**********************************************************************
			
setup
      
     ; BSF	STATUS,RP0 ;Jump to bank 1 use BANKSEL
	BANKSEL TRISB	
	MOVLW	B'11110001'	; PORTB, RB1-3 OUTPUT, RB0, RB4-7, RA0 INPUT
	MOVWF	TRISB		; Set I/O configuration for PORTB
	MOVLW   B'00000011' ; Enable TMR0, prescale 1:16
	MOVWF   OPTION_REG    
	; BCF	STATUS,RP0	;Jump back to bank 0 of PIC.
	BANKSEL INTCON
	CLRF 	INTCON	; No INT needed for TMR0 just check flag BIT 2
	CLRF	PORTB	;Clear all I/O's of PORTB

goto main

main
	movlw   0x02  ;  toggle bit RB1
	xorwf   PORTB, 1 
	movlw .100
	call Wx10ms
goto main

;		**************************	;Delay routine.
	; Presccale / 16 and TMR0 = prelaod 195 = ~1 kHz.
	; 1,000,000 prescale 256, TMR0 = 256 = 15.26 Hz.
	; Measured 7.6 Hz, LED on RB2 takes 2 counts per cycle.
delay1ms
	; 4 mHz crystal, precale / 16 = 16uSec.
	; 256 - 194 = 62; 62 * 16 uSec. = 992 uSec. = ~1 mSec. 
	; Vary preload value based on actual XTAL freq.
	movlw D'195'
	movwf TMR0 ; Load TMR0
	bcf INTCON, 2 ; CLR TMR0 Flag begin count
	btfss INTCON, 2 ; Wait for bit set
	goto $-1
	return

delay10ms
	movlw .10
	goto $+2 ; skip next
Wx1ms	; W * 1mSec.
	movwf CNT4
	call delay1ms
	decfsz CNT4, f
	goto $-2
	return

Wx10ms	; W * 10mSec.
	movwf CNT3
	call delay10ms
	decfsz CNT3, f
	goto $-2
	return

END

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

PIC16F84A Test Circuit



Web site Copyright Lewis Loflin, All rights reserved.
If using this material on another site, please provide a link back to my site.