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.

  • 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.

pic16f882 timer1 clock crystal

Status
Not open for further replies.

birdman0_o

Active Member
Hey guys, I just can't seem to make it work!
It's running 1s faster than it should be every minute!!!

Here's my code, maybe you can spot something out!

32.768Khz Osc, Two 10pF caps.

Code:
;*************************************
; Author  : Mike Baird
; Program : Clock
; Date    : October 23rd,2009
;*************************************

	List	P=16F882
	#include	"P16F882.INC"
	__CONFIG	_CONFIG1,   _PWRTE_ON  & _WDT_OFF & _INTOSC & _BOR_OFF & _LVP_OFF & _CP_OFF & _MCLRE_OFF
	__CONFIG    _CONFIG2,	_IESO_OFF & _FCMEN_OFF
;*** Cblock ***

	CBLOCK	0x20		 
	d1									; 
	d2									;
	SecLow								;
	SecHigh								;
	MinLow								;
	MinHigh								;
	HourLow								;
	HourHigh							;
	MinL								;
	MinH								;
	HourL								;					
	HourH								;
	W_TEMP								;
	STATUS_TEMP							;
	X									;
	TEST								;
	ENDC

;*** Defines ***

#Define 	Bits 		PORTB,2
#Define 	Clock		PORTB,1
#Define 	Latch		PORTB,0
#Define 	MLow		PORTC,4
#Define 	MHigh		PORTC,5
#Define		HLow		PORTC,6
#Define 	HHigh		PORTC,7

;*** Macro ***

HC595 MACRO Var,Var1

	Local	Loop						; Local Label
	MOVLW	.8							; Transfer 8 bits
  	MOVWF	Var1						; Initializing counter

Loop	
	RLF 	Var,f						; Rotate "Var" one place to the left
	BTFSS	STATUS,C					; Is carry 1?
	BCF 	Bits						; If not set data line to 0
	BTFSC 	STATUS,C					; Is carry 0?
	BSF 	Bits						; If not set data line to 1

	BSF 	Clock						; Generate one clock
	BCF	 	Clock						;	

	DECFSZ 	Var1,f						; Has 8 bits been sent?
	GOTO	Loop						; If not, repeat

	BSF 	Latch						; If all 8 bits have been sent, set latch
	BCF 	Latch						;
	
	RLF 	Var,f						; Restore to Orginal
	ENDM


;*** START OF RAM ***
	ORG	0x000							; Start of program vector
	GOTO	Start						;
	ORG	0x004							; Interrupt vector

;*** Interrupt Service Routine ***

ISR: 
	MOVWF 	W_TEMP						; 	
	SWAPF 	STATUS,W   					; Context Saving
	MOVWF 	STATUS_TEMP					; 					

	BCF 	PIR1,TMR1IF					; Clear Interupt Flag
	BSF 	TMR1H,7						; Reload the start up value into the timer


;*** Code Insert ***
;	INCF	SecLow
;	MOVF	SecLow,W
;	SUBLW	.10
;	BTFSS	STATUS,Z
;	GOTO	Exit
;	CLRF	SecLow

;	INCF	SecHigh
;	MOVF	SecHigh,W
;	SUBLW	.6
;	BTFSS	STATUS,Z
;	GOTO	Exit
;	CLRF	SecHigh

	INCF	MinLow
	MOVF	MinLow,W
	SUBLW	.10
	BTFSS	STATUS,Z
	GOTO	Exit

	CLRF	MinLow
	INCF	MinHigh
	MOVF	MinHigh,W
	SUBLW	.6
	BTFSS	STATUS,Z
	GOTO	Exit	

	CLRF	MinHigh
	INCF	HourLow

	BTFSS	TEST,1
	GOTO	TwoHours

	MOVF	HourLow,W
	SUBLW	.10
	BTFSS	STATUS,Z
	GOTO	Exit
	GOTO	$+5

TwoHours
	MOVF	HourLow,W
	SUBLW	.3
	BTFSS	STATUS,Z
	GOTO	Exit


	BTFSC	TEST,1
	GOTO	One
Blank
	MOVLW	.1
	MOVWF	HourLow
	MOVLW	.10
	MOVWF	HourHigh		
	BSF		TEST,1
	GOTO	Exit
One
	CLRF	HourLow
	MOVLW	.1
	MOVWF	HourHigh
	BCF		TEST,1
	
;*** End of Insert ***

Exit
	SWAPF 	STATUS_TEMP,W				; Restore Status and W	
	MOVWF	STATUS						;
	SWAPF 	W_TEMP,F					;
	SWAPF 	W_TEMP,W					;
	RETFIE								;

;*** End of ISR ***

Start

	CLRF	PORTA						; PortA all low
	CLRF	PORTB						; PortB all low
	
	BSF		STATUS,RP0					; Bank 1
	CLRF	TRISA						; PortA all output except MCLR
	CLRF	TRISB						; Move to PortB
	CLRF	TRISC

	BSF		TRISC,0						; Osc inputs
	BSF		TRISC,1

	BSF		PIR1,TMR1IE

	BCF		STATUS,RP0					; Bank 0		

	BANKSEL	ANSEL
	CLRF	ANSEL
	CLRF	ANSELH

	BANKSEL	PORTA


;*** Timer1 set up ***

	BCF		T1CON,6
	BCF 	T1CON,4            			; 1,2,4,8 prescaler  
	BCF 	T1CON,5            			; 
					
	BSF 	INTCON,6					; Enable all unmasked interrupts
	BSF 	INTCON,7           			; Enable Global interrupts

	BSF		TMR1H,7							; Load a start up value into the timer

;	MOVLW 	b’00001111’ ; Configure for external clock, from pic16f88 datasheet
;	MOVWF 	T1CON ; Asynchronous operation, external oscillator

	BSF		T1CON,T1OSCEN	;3			; Timer1 External Clock Input Synchronization Control bit

	BSF		T1CON,T1SYNC	;2			; Sync to external clock

	BSF		T1CON,TMR1CS	;1			; External clock from pin RB6/T1OSO/T1CKI/PGC (on the rising edge)

	BCF 	PIR1,0             			; Reset interupt flag

	BSF 	T1CON,0			;0			; Start the timer


	MOVLW	d'0'
	MOVWF	SecLow
	MOVLW	d'0'
	MOVWF	SecHigh
	MOVLW	d'0'
	MOVWF	MinLow
	MOVLW	d'0'
	MOVWF	MinHigh
	MOVLW	d'2'
	MOVWF	HourLow
	MOVLW	d'1'
	MOVWF	HourHigh

	CLRF	TEST


Main:
	Call 	TurnOffNumbers
	MOVF	MinLow,W
	Call 	Table
	MOVWF	MinL
	HC595 	MinL,X
	BSF		MLow	
	Call 	Delay

	Call 	TurnOffNumbers
	MOVF	MinHigh,W
	Call 	Table
	MOVWF	MinH 
	HC595	MinH,X
	BSF		MHigh
	Call	Delay

	Call 	TurnOffNumbers
 	MOVF	HourLow,W
	Call 	Table
	MOVWF	HourL
	HC595 	HourL,X
	BSF		HLow
	Call 	Delay

	Call 	TurnOffNumbers
 	MOVF	HourHigh,W
	Call 	Table
	MOVWF	HourH
	HC595 	HourH,X
	BSF		HHigh
	Call 	Delay

	GOTO 	Main

TurnOffNumbers:
	BCF 	MLow
	BCF 	MHigh
	BCF 	HLow
	BCF 	HHigh
	RETURN	

Table:
	ADDWF	PCL
	RETLW 	b'00111111' 				; 0	    (3)
	RETLW 	b'00000110' 				; 1	    (4) 
	RETLW 	b'01011011' 				; 2	    (5)
	RETLW 	b'01001111' 				; 3	    (6)
	RETLW 	b'01100110' 				; 4	    (7)
	RETLW 	b'01101101' 				; 5	    (8)
	RETLW 	b'01111101' 				; 6	    (9)		
	RETLW 	b'00000111' 				; 7	    (10)
	RETLW 	b'01111111' 				; 8	    (11)
	RETLW 	b'01101111' 				; 9     (12)
	RETLW	b'00000000'					; Blank

; *** Delay ***
Delay	
	MOVLW	d'6'
	MOVWF	d1
D1	MOVLW	d'20'
	MOVWF	d2
	
D2	DECFSZ	d2,F
	GOTO	D2
	DECFSZ	d1,F
	GOTO	D1
	RETURN

;***

	END
 

Wp100

Well-Known Member
Hi,


Don't know the exact parameters of the 32k xtal you are using, but the ones I have used give good time, to seconds per week, when using 22, 27 or 33 pf.
 

Mr RB

Well-Known Member
Strip it down to the most basic code you can use to make a second. With a 32kHz xtal clocking TMR1 that's pretty easy, you set the TMR1 prescaler so it overflows (and makes an interrupt) every second.

Just get it to toggle a LED once a second at first. You can test that against your watch. Once you have that working and tested for accuracy you can fluff out the code to do minutes and hours etc.
 

Pommie

Well-Known Member
Most Helpful Member
Strip it down to the most basic code you can use to make a second. With a 32kHz xtal clocking TMR1 that's pretty easy, you set the TMR1 prescaler so it overflows (and makes an interrupt) every second.

I'd like to see how you set the prescaler to 0.5!:eek::D

On a more serious note, the code he is using is the example code from the 16F88 data sheet. I can't see why it would be inaccurate and think it must be hardware related.

Mike.
 

Pommie

Well-Known Member
Most Helpful Member
Just had a look through the 16F88 data sheet and Microchip suggest 33pF caps with the LP crystal. Can you change your caps and make sure the crystal is as close as possible to the chip.

Mike.
 

Pommie

Well-Known Member
Most Helpful Member
Well, you got me curious and so I added a 32k crystal to a board I have with a 16F886 on it. I used 15pF capacitors and the following code,
Code:
#include <system.h>
#include "LCD.c"

#pragma DATA _CONFIG, _DEBUG_ON & _MCLRE_ON
                    & _CP_OFF & _PWRTE_OFF
                    & _WDT_OFF & _INTOSCIO
                    & _LVP_OFF

char PK2_Reserved @0x70;
unsigned char seconds,minutes,hours,oldseconds;

void main(void){
    while(!osccon.HTS);
    osccon=0x71;            //8 meg
    ansel=0;
    anselh=0;
    option_reg=0b00000000;  //wpu on
    InitLCD();
    hours=0;
    minutes=0;
    seconds=0;
    oldseconds=0;
    [COLOR="red"]t1con=0b00001111[/COLOR];
    pie1.TMR1IE=1;
    intcon.PEIE=1;
    intcon.GIE=1;
    while(1){
        if(seconds!=oldseconds){
            oldseconds=seconds;
            SetPos(0,0);
            PutDecimal(hours);
            PutChar(':');
            PutDecimal(minutes);
            PutChar(':');
            PutDecimal(seconds);
        }
    }
}

void interrupt(void){
    if(pir1.TMR1IF){
        pir1.TMR1IF=0;
        [COLOR="Red"]tmr1h.7=1;[/COLOR]
        if(++seconds==60){
            seconds=0;
            if(++minutes==60){
                minutes=0;
                if(++hours==24)
                    hours=0;
            }
        }
    }
}
It's now been running 15 minutes and appears to be keeping excellent time.

I know this is in C but it is using the hardware in an identical way to you. I highlighted the relevant bits.

Edit, now been running over 8 hours and still spot on.

Mike.
 
Last edited:

Mr RB

Well-Known Member
I'd like to see how you set the prescaler to 0.5!:eek::D
...

Mr Smarty Pants! :D You could tell I typed that in a hurry huh?

I remember whan I used a Dallas temp compensated 32kHz that i set it up to automatically TMR1 interrupt every second. Now I think about it the prescaler was set to 1:1 and I just set TMR1.F7 like in your examples.

The reason I posted that was because i thought his timer may have been right but there could be a bug in the seconds/minutes incrementing, that would be an obvious cause of a +1 sec per min error. Checking the seconds themselves for accuracy would separate the bug into either faulty timing or faulty seconds incrementing. Bugs like that can be a bit hard to catch in the simulator.
 

birdman0_o

Active Member
It must be a capacitor error. With 10pF, the timing was ~ 1s /Min. With 33pf it was ~1s/5min and with around 5 pf it was ~ 1 s/17 min.

This is much more frustrating then I wanted it to be :)
 

kpatz

New Member
Are you using a breadboard? The contact strips add a few pF of capacitance themselves. Try it without any caps and see what you get, if that's the case.

Do you have an oscilloscope so you can verify the crystal waveform with different caps?
 

Pommie

Well-Known Member
Most Helpful Member
Mine is on a breadboard with 15pF caps and is still keeping good time after a day.

Mike.
 

Mike - K8LH

Well-Known Member
I suspect not all solderless breadboards are created equal (lol). The very old solderless breadboard I have doesn't like crystals at all.

Regards, Mike
 

Sceadwian

Banned
Pommie, put the same circuit on a perfboard, I garuntee it won't keep the same time.
 

Sceadwian

Banned
You could do that, but you'll have to use a variable cap to tune this on the final board, or retune it completly once it's in it's final enclosure. Scope leads don't help either.
 
Status
Not open for further replies.

EE World Online Articles

Loading
Top