• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC16F887 Timer1 problems

Status
Not open for further replies.

bones_bones

New Member
Hi
I seem to be having dificulty using the Timer1 module to increment every second. As I understand it there is a 32.768KHz crystal clock built into the PIC on pins PORTC.0 and PORTC.1 (If I'm incorrect in this fact please let me know) and there is no need to build a crystal-cap circuit.

In my code I would like to have a HIGH output on PORTD.0 every minute and as soon as the comparator meets the requirements, to then pull PORTD.0 LOW. However timer1 doesn't seem to incremet at all.

There are no problems wth the comparator section as I've used that bit of code for another circuit that functioned perfectly and therfore i'll leave out that bit.

Could someone please have a quick look at my code and see if you can spot the problems.

Thanks in advance.

PHP:
#include	"D:\Program Files\Microchip\MPASM Suite\p16f887.inc"   ;yes that is my root drive

	__config _CONFIG1, (_INTRC_OSC_CLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF & _LVP_OFF)
	__config _CONFIG2, (_BOR40V & _WRT_OFF)

                                                        ;vaiable declarations
	cblock	0x20
	minutes
	seconds
	count
	endc

                                                        ;reset and ISR
	org		0x00
	goto	reset
	org		0x04
	goto	isr

reset
;====================================================================================
                                                        ;setting up timer1 for 1 sec increments
	bcf		STATUS, RP0
	bcf		STATUS, RP1		;bank 0
	movlw	0xbe
	movwf	T1CON		        ;timer1 is set to increment every sec but is not yet enabled-
	clrf	PORTC		                ;using 32.768 crystal clock and a prescaler of 1:8

	bsf		STATUS, RP0		;bank 1
	movlw	0x03
	movwf	TRISC			;set PORTC.0 and PORTC.1 ans inputs

	bcf		STATUS, RP0		;bank 0
		;interrupt for timer1
	movlw	0x40
	movwf	INTCON			;enable Peripheral Interrupts

	bsf		STATUS, RP0		;bank 1
	bsf		PIE1, 0			;enable overflow interrupt

	bcf		STATUS, RP0		;bank 0
							;timer 1 set up but not enabled
;====================================================================================

                                                        ;setting up on off switch and clearing variables
;====================================================================================
	clrf	TRISD

	bcf		STATUS, RP0		;bank 0
	clrf	PORTD
	clrf	PORTC
	clrf	PORTA
	
	call	oc_delay		                 ;call delay for crystal to settle
	
	clrf	seconds			         ;register to increment seconds
	clrf	minutes			         ;register to increment minutes
	clrf	count			                 ;register used in delay loop
	clrf	TMR1H			         ;clear timer1 to start at 0
	clrf	TMR1L
	bsf		T1CON, 0		         ;enable timer1
	bsf		INTCON, 7		         ;interrupts enabled
;====================================================================================

                                                         ;main function
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
main_loop
	call	test_time		                 ;function to test if a minute has gone by
	nop
goto	main_loop

test_time
	movlw	0x01			         ;test condition (this may seem comlicated for a min, but in future i want to have longer periods)
	subwf	minutes, 0		
	btfss	STATUS, C		                 ;has the varible minutes reached a min
return						 ;NO -- then do nothing
 	call	comparitor_on	;Yes -- turn on comparitor to use as a kill switch-
	bsf		PORTD, 0		          ;       and pull PORTD.0 HIGH
return
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
isr
		                                         ;test if interrupt was generated correctly
	btfsc	PIR1, 0
	goto	sec_inc
retfie						         ;if not return to main loop

sec_inc
	bcf		PIR1, 0			
	incf	seconds			          ;increment seconds-
	movlw	0x3c			          ;and test if seconds has reached 60(decimal)
	subwf	seconds, 0
	btfss	STATUS, C
	goto	end_isr			          ;IF seconds != 60 return to main loop through an isr end procedure
	clrf	seconds			          ;IF seconds == 60 clear seconds-
	incf	minutes			          ;and incremet minutes
	goto	end_isr

end_isr						   ;ISR end procedure
	bcf		STATUS, RP1
	movlw	0xc0
	movwf	INTCON
retfie
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


oc_delay					;delay loop for crystal
	movlw	0xff
	movwf	count
	back
	decfsz	count
	goto	back
return

end
 
Last edited:

kpatz

New Member
Timer1 has a built-in oscillator but you still have to provide the crystal and supporting caps to use it. Look at page 66 of the datasheet for the circuit for using a crystal with the LP oscillator. For timer1 you'd do the same thing but the crystal/cap circuit would be connected between the T1OSO and T1OSI pins.

Set the prescaler to 0. When using a 32768 KHz crystal, the timer will increment 32768 times per second. The timer interrupt isn't generated until the timer overflows, when it reaches 65535 and rolls back to zero. So, the way your code is now, you'll only get a timer1 interrupt once every 16 seconds. So, set the prescaler bits to 0, and set bit 7 of TMR1H when you start the timer and also everytime the timer interrupt occurs. This resets the timer to 32768 so it only needs 1 second to overflow. Then you'll get a timer interrupt once per second, which you can use for your timing.
 
Last edited:
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top