# Clock based on a 16F628 pic

Status
Not open for further replies.

#### ced

##### New Member
Hi,
I am trying to get from a 16F628 a 1 Hz square wave pulse on PORTB0 and it gets desperately stuck at 0V .
I've tied PORTB0 to a 2k Ohm resistor .

I've coded the program in assembler, compiled it with Mplab IDE and downloaded it to the
pic thanks to easypic4 dev board .

I use LS oscillator mode with a 32kHz crystal .
I've checked on RA6/OSC2/CLKOUT the sine wave that looks fine .

The main loop does nothing ,
The interrupt service routine loads PORTB at each Timer0 interrupt in W register, then 1 - W is computed and written to PORTB

As PORTB is initialized as 0, I thought it would oscillate between 0 and 1,
but it doesn't :-( .

Here is the code, if someone has some spare time :

#include "p16f628.inc"
__CONFIG _LP_OSC & _PWRTE_ON & _BODEN_ON & _MCLRE_OFF & _WDT_OFF & _CP_OFF

RESET org 0x0000
goto Main

INTERRUPTION org 0x0004
GOTO ISR

ISR

bcf INTCON, T0IF

movf PORTB, W
sublw 1
movwf PORTB
retfie

Main

bsf STATUS,RP0
bcf OPTION_REG, PSA
bcf OPTION_REG, PS2

bcf OPTION_REG, T0CS

bcf STATUS,RP0
CALL PORTB_INIT
bcf INTCON, T0IE
bcf INTCON, GIE

INF_LOOP
nop
goto INF_LOOP

PORTB_INIT

bsf STATUS,RP0
bcf TRISB,0

bcf STATUS, RP0

clrf PORTB
return
END

Cédric

Last edited:

#### Pommie

##### Well-Known Member
Here is your code and I've highlighted the problem,
Code:
		#include "p16f628.inc"
__config _LP_OSC & _PWRTE_ON & _BODEN_ON & _MCLRE_OFF & _WDT_OFF & _CP_OFF

RESET		org	0x0000
goto	Main

INTERRUPTION	org	0x0004
goto	ISR
ISR
bcf	INTCON, T0IF
movf	PORTB, W
sublw	1
movwf	PORTB
retfie

Main
bsf	STATUS,RP0
bcf	OPTION_REG, PSA
bcf	OPTION_REG, PS2
bcf	OPTION_REG, T0CS
bcf	STATUS,RP0
call	PORTB_INIT
b[COLOR="Red"]s[/COLOR]f	INTCON, T0IE
b[COLOR="red"]s[/COLOR]f	INTCON, GIE
INF_LOOP
nop
goto	INF_LOOP

PORTB_INIT
bsf	STATUS,RP0
bcf	TRISB,0
bcf	STATUS, RP0
clrf	PORTB
return
end
BTW, to post code and keep it formated, put [code] before it and [/code] after it.

HTHs.

Mike.

#### ced

##### New Member
Thanks very much Mike
I'll try it now,
Bye

#### ced

##### New Member
Hi,
There must be some other errors as PORTB stays at 0 V .

#### ced

##### New Member
On another forum, someone tested my code, and it worked ?!?
Maybe the pic doesn't work anymore, or maybe the problem comes from the mikroelektronika programmer .
I'll have to do other tests to check that ...

#### birdman0_o

##### Active Member
Try a simple LED flash program that works first,
actually this program operates at rougly 1Hz (995ms).
Should work!

Code:
;*************************************
; Author  : Mike Baird
; Program : LED Flash
; Date    : September 6th, 2009
;*************************************

List	P=16F628a
#include	"P16F628a.INC"
__CONFIG	_PWRTE_ON  & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_ON & _LVP_OFF & _CP_OFF & _MCLRE_OFF

;*** Cblock ***

CBLOCK	0x20
d1									; For delay!
d2									;
d3									;
ENDC

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

;*** Configuration ***

Start
MOVLW	0x07						; Turn comparators off and enable pins for I/O
MOVWF	CMCON						; ^
CLRF	PORTA						; PortA all low
CLRF	PORTB						; PortB all low

BSF		STATUS,RP0					; Bank 1
MOVLW	b'00100000'					; Bit 5 input
MOVWF	TRISA						; PortA all output except MCLR
CLRF	TRISB						; PortB all output
BCF		STATUS,RP0					; Bank 0

;***

Main
MOVLW	0xFF						; Turn all pins ON
MOVWF	PORTB						; Move to PortB
CALL 	Delay						; Call 1 second delay
MOVLW	0x00						;
MOVWF	PORTB						;
CALL	Delay						;
GOTO 	Main						;

;*** Delay ***
Delay
MOVLW	d'255'
MOVWF	d1
MOVLW	d'255'
MOVWF	d2
MOVLW	d'5'
MOVWF	d3

D2	DECFSZ	d1,F
GOTO	D2
DECFSZ	d2,F
GOTO	D2
DECFSZ	d3,F
GOTO	D2
RETURN

;********************

END

; That's all folks!

#### ced

##### New Member
Thanks Mike for your help .
Meanwhile I have programmed the same hex file on a 16F84A and it works nice .
It seems that the source of the bug was the 16F628 pic .
By the way , the 16F84A oscillates a little slowyer than expected with two 100 nF ceramic capacitors linked to the 32 kHz crystal .
Should I lower the values of these capacitors to get a better frequency ?
Bye

#### Nigel Goodwin

##### Super Moderator
By the way , the 16F84A oscillates a little slowyer than expected with two 100 nF ceramic capacitors linked to the 32 kHz crystal .
Should I lower the values of these capacitors to get a better frequency ?
Where did you get the value of 100nF from?, those are FAR too high, I'm amazed it runs at all.

#### ced

##### New Member
Oops, you are right, it's a mistake, I've put 100 pF capacitors

#### birdman0_o

##### Active Member
The 16f628a has an internal oscillator, why not use it?

#### kpatz

##### New Member
The 16f628a has an internal oscillator, why not use it?
The internal oscillator isn't as accurate as a crystal. He's making a clock and thus he needs it to be accurate.

But, there's no reason the OP can't use the internal oscillator for testing/debugging (to rule out the crystal circuit as being the cause) and then switch over to using the crystal once the code is working.

Last edited:

#### birdman0_o

##### Active Member
He hasn't stated the application and his code doesn't look like it will be displaying "time". I assume he is just making an astable clock to flash an LED for now. He should get the code working before he tries to get it more accurate

#### Pommie

##### Well-Known Member
The best way to do this, assuming current consumption is not a problem, is to use the internal oscillator to run the chip and use the Timer1 oscillator for timing. Example code is in the 16F88 data sheet. You can still use the 32K crystal as the main oscillator but if you want it to do anything else you need it to run faster.

BTW, whoever told you on another forum that your code worked was lying or mistaken. It could not possibly work as posted originally.

Mike.

#### ced

##### New Member
Hi,
using the prescaler and timer0 , the signal period I get is 1,000045 s instead of 1s according to the quite cheap counter I use .
That means that the clock would be 4s late each day, one minute every 15 days it's bearable .
I am willing to do a clock, and for what I've understood, the 32kHz clock is divided by 4 to get the
instruction clock.
The pic should be able to execute more or less 8000 instruction each second, so 8000/50= 160 instruction for the four 7 segments display at 50 Hz , thus 40 instructions per 7 segment display .
It's going to be a tricky, and it may flicker a little bit, we'll see that later .

Nobody lyed, as I answered you, after these two modifications, it still didn't work because of the pic and someone else tested the modified code and told me that it worked. And it does, as I tested it on a
16F84.
Well, it's certainly going to be short, but I'll try it .

#### Mr RB

##### Well-Known Member
I've got a feeling your PIC is not running, the 16F628 osc is a little fussy (it's much more fussy than the 16F84A) and you have 100pF caps, and it's probably on a plug-in breadboard which adds 50pF or so to the osc pins.

Try running it without the 100pF caps at all if it is on a breadboard. And/or change the _LP_OSC to _XT_OSC and try that, some of the larger size 32kHz xtals need the XT setting.

Code:
	MOVLW	0x07						; Turn comparators off and enable pins for I/O
MOVWF	CMCON						; ^
from birdman's code.

If you want an easy and *adjustable* way to make a 1 second period using PIC TMR0 there are some ASM and C examples here;

Zero-error 1 second timing algorithm

(edit) Also the code on that link I posted lets you use ANY freq xtal, so if you need faster PIC speed (as you mentioned above) and don't have a xtal you can just pull one out of any old junked appliance VCR/TV/PC motherboard etc.

Last edited:

#### birdman0_o

##### Active Member
32.768 Khz should divide nicely into exactly one second, which clock did you use to end up with 1.000045s?

#### kpatz

##### New Member
The best way to do this, assuming current consumption is not a problem, is to use the internal oscillator to run the chip and use the Timer1 oscillator for timing. Example code is in the 16F88 data sheet...
And if current consumption is a problem, you can set the internal oscillator to the slowest speed you need to execute the instructions you need to be able to execute between timer interrupts. Or, use a faster speed and put the PIC to sleep when it comes time to wait for the next timer interrupt. Timer1 will continue running when using the crystal while the PIC is asleep and use very little power, and the PIC will wake up when Timer1 overflows.

With a 32,768Hz crystal and some code to preload the MSB of the timer after each overflow, you can get a reasonably accurate 1 second timer.

Last edited:

#### ced

##### New Member
Hi Mike,
I am using timer0, and prescaler set up to divide by 16 the Timer0 interrupts.
Actually I thought it was not that bad to get a 1,000045 s period, as there's no chance
to get exactly 1 s.
Did you check the period of your clock signal with a counter ?
If you succeed to get an exact 1s period , I am very interested ...

#### kpatz

##### New Member
Hi Mike,
I am using timer0, and prescaler set up to divide by 16 the Timer0 interrupts.
Actually I thought it was not that bad to get a 1,000045 s period, as there's no chance
to get exactly 1 s.
That is actually quite good. Using the techniques mentioned in the link Mr RB posted, you can compensate for that .000045 second in software and get your clock spot-on.

That's only 45 microseconds. That may just be code execution delay, which you can adjust for in your code.

One time I wrote a routine for a baseline PIC12 (one w/o interrupts, and using Timer0) that allowed me to get a delay of an exact multiple of 100µs based on a 4 MHz clock. With some tweaking it can be changed to a 1ms or 1s delay, and with a few minor tweaks, it can be tuned to be spot-on. Of course, spot on if you can get your crystal tuned to exactly 4.00000000 MHz.

Last edited:

#### ced

##### New Member
By software, with a quicker crystal that should certainly be fixed.
Well, maybe i'll get lazy and accept this slight error anyway
Nevertheless, I still have a question about pics.
Actually at the beginning I planned to use a 16F676, and it is still what I want to do.
I just used a spare 16F628 as among the 3 16F676's that I had up to yesterday, none were correctly recognized by the easypic4 dev board .
Today, I bought to other ones, and I'll try in the next days to program one of those.
Setting up time seems to me a reasonably necessary feature ;-) .
Up to know, I thought I would use the 6 pins from PORTA of the pic16F676 like this :
4 bits as input for the BCD to 7 segments decoder and 2 bits for one of the two
2->4 decoder of a 74LS139 , reserving PORTB to get the minutes and hour increment inputs and the alarm_triggered and set_alarm signals .
alarm_triggered and set_alarm signals should be steady and can be treated easily, but minutes and hour increment should be pulses .
So I am wondering how I could get a single interrupt from these 2 signals .
Would you have some ideas ?

Status
Not open for further replies.