Continue to Site

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.

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

Thanks for your help,

Cédric
 
Last edited:
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.
 
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 ...
 
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!
 
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
 
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.
 
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:
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 :)
 
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.
 
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 .
 
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.

Also you should add the;
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:
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:
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 ...
 
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:
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.

New Articles From Microcontroller Tips

Back
Top