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.

Can't get my pic16f628 to blink

Status
Not open for further replies.

mattg2k4

New Member
I'm programming my pic16f628 in assembly to get a led blinking. I can get the led to turn on, but it isn't blinking. Here's my code:

Code:
STATUS	equ 	03h
PORTA 	equ 	05h
TRISA 	equ		85h
count1	equ		07h
count2	equ		08h

;***set up ports, all porta pins to output***

		bsf 	STATUS,5		;go to bank 1
		movlw	b'00000000'		;set trisa,
		movwf	TRISA			;so all porta are outputs
		bcf		STATUS,5		;now to bank 0

;Blinking portion of program start point

Start

;turn all PORTA ports high

		movlw	b'11111111'		;set all porta pins,
		movwf	PORTA			;to 1

;call a delay before turning leds off

		call	LongDelay

;now turn all leds off

		movlw	b'00000000'		;set all porta pins,
		movwf	PORTA			;to 0

;Call a delay
		
		call	LongDelay

;Now go back to start so the cycle repeats

		goto	Start

;***Delay subroutine, inserts a short delay
Delay
		movlw	0xff
		movwf	count1
loop1
		decfsz	count1,1
		goto	loop1
return

;***LongDelay subroutine, inserts a long delay
LongDelay
		movlw	0xff
		movwf	count2
loop2
		call 	Delay
		decfsz	count2,1
		goto	loop2
return


;end program
		end
Config bits:
Osc- IntRC Clkout
watchdog- off
power up timr- off
brown out detect- off
mclr enable- enabled
LV program- enabled
data ee read protect- off
code protect- off

The circuit has power hooked up, MCLR connected to +5v, a 4017 with clock pin on RA2, and a led with resistor on RA3. Power is provided from a 9v battery with a 7805 linear regulator.

I attached a 4017 decade counter to the RA2 pin to see if it was just blinking too fast to see. It's inconclusive. The light will start on different leds with no apparent pattern, but it will not move after that. The led on RA3 is always lit when power is connected.

Does anyone have any ideas?
 
There are 2 ways to try something...

a) use tmr0 to define your 'delay' and I prefer this the most, as you can accurately define the delay based on your clock speed

b) try this code (configed for a 4Mhz clock)

Code:
;.................................................................
;=======10s DELAY LOOP=========================================
;This is 10second delay.
Delay
	clrwdt
	movlw	d'40'		;move 40 to wreg
	movwf	cnt1		;move wreg to cnt1
loop3	movlw	d'255'		;move 255 to wreg
	movwf	cnt2		;move wreg to cnt2
loop2	movlw	d'255'		;move 255 to wreg
	movwf	cnt3		;move wreg to cnt3
loop1	clrwdt
	decfsz	cnt3,F		;decrease cnt3 till zero
	goto	loop1		;if (cnt3 != 0) then goto loop1
	decfsz	cnt2,F		;decrease cnt2 till zero
	goto	loop2		;if (cnt2 != 0) then goto loop2
	decfsz	cnt1,F  	;decrease cnt1 till zero
	goto	loop3		;if (cnt1 != 0) then goto loop3
	return

Play with the value '40' to get the timing how you like it. Also remember to load the osc config value from the special memory space @ boot to calibrate your intrc - look @ data sheet!!!

Also for your port declaration you can use this instead

Code:
      bsf        STATUS,5      ;go to bank 1 

      movlw   b'00000000'      ;set trisa, 
      movwf   PORTA         ;so all porta are outputs 

      bcf        STATUS,5      ;now to bank 0

but that's not too important. Also for return use 'retlw 0' ....see if these help...

Not had so much trouble in blinking leds tbh.

Also double check that you arn't pulling too much current from each port for the leds (I know you said you used resistors)....
 
Okay, I tried your suggestions bsodmike. I wasn't sure about loading the osc config value though. I found in the datasheet the OSCF bit of PCON, which defaults to 1, which is 4Mhz. Is that what you were talking about?

Here is the revised code:
Code:
STATUS	equ 	03h
PORTA 	equ 	05h
TRISA 	equ		85h
cnt1	equ		07h
cnt2	equ		08h
cnt3	equ		09h
F		equ		1

;***set up ports, all porta pins to output***

		bsf 	STATUS,5		;go to bank 1
		movlw	b'00000000'		;set trisa,
		movwf	PORTA			;so all porta are outputs
		bcf		STATUS,5		;now to bank 0

;Blinking portion of program start point

Start

;turn all PORTA ports high

		movlw	b'11111111'		;set all porta pins,
		movwf	PORTA			;to 1

;call a delay before turning leds off

		call	Delay

;now turn all leds off

		movlw	b'00000000'		;set all porta pins,
		movwf	PORTA			;to 0

;Call a delay
		
		call	Delay

;Now go back to start so the cycle repeats

		goto	Start

;.................................................................
;=======10s DELAY LOOP=========================================
;This is 10second delay.
Delay
   clrwdt
   movlw   d'40'      ;move 40 to wreg
   movwf   cnt1      ;move wreg to cnt1
loop3   movlw   d'255'      ;move 255 to wreg
   movwf   cnt2      ;move wreg to cnt2
loop2   movlw   d'255'      ;move 255 to wreg
   movwf   cnt3      ;move wreg to cnt3
loop1   clrwdt
   decfsz   cnt3,F      ;decrease cnt3 till zero
   goto   loop1      ;if (cnt3 != 0) then goto loop1
   decfsz   cnt2,F      ;decrease cnt2 till zero
   goto   loop2      ;if (cnt2 != 0) then goto loop2
   decfsz   cnt1,F     ;decrease cnt1 till zero
   goto   loop3      ;if (cnt1 != 0) then goto loop3
   retlw 0    

;end program
		end

It is still not blinking so far as I can see, just staying solidly lit, and I've been watching it for at least a minute now.

Edit: While browsing threads here I clicked on from his signature, and copy pasted the code into MPLAB and it's now blinking (Thanks Nigel!). Now I'm going through and adjusting my code piece by piece to be like his so I can see where I went wrong.

Edit2: Okay, I have located the problem:
Code:
cnt1   equ      07h
cnt2   equ      08h
cnt3   equ      09h
Since these were blank in the memory map I just assumed I could use them, but that's wrong. Changing them to 0x20, 21, and 22 solves the problem.
 
Glad it works!

Btw here is a how I declare my variables now:

Code:
MEMORY	EQU	20h

var1	EQU	MEMORY+1
var2	EQU	MEMORY+2
var3	EQU	MEMORY+3

Of course the danger in reusing code is that you *forget* to update the memory location (specially when you change from PIC to PIC) and the 20h is for the 12C672.

My code was going bonkers as I had it set to the memory map value for 16F84 - d'oh!

I suggest you start playing with tmr0 as that is the best way to get perfect delays.

Osc Config:

What I'm talking about is 'OSCCAL'. It applies to some PICs that have the option for an internal osc. With the INTRC you need to calibrate the osccal @ boot by using code such as this:

Code:
	org	00h		;the reset vector is defined as address 00hex
	call	07FFh		;get calib info into wreg

	bsf	_status,5	;move into bank 1

	movwf	_osccal		;calibrate the Int Osc

	bcf	_status,5	;move into bank 0

   	goto	Setup		;and we tell it to go to 'Init'

Again the 07FFh address is for the 12C672. The datasheet says that @ this location there is a command 'retlw xx' stored. That is how the code continues and you can see how the 'movwf' calibrates the osccal!
 
Try this, this is the proper way to define variables.

Code:
	cblock 0x20
	var1
	var2
	var3
	endc

If you want to add another just place it under var3.

all equ does is replace any existence of var1 with 0x20 if you do it like :

var1 equ 0x20

Ron[/code]
 
Try this, this is the proper way to define variables.

Code:
	cblock 0x20
	var1
	var2
	var3
	endc

If you want to add another just place it under var3.

all equ does is replace any existence of var1 with 0x20 if you do it like :

var1 equ 0x20

Ron
 
Ahh very nice...

So *that* is what 'cblock' does ;)

Cool stuff :D
 
bsodmike said:
Ahh very nice...

So *that* is what 'cblock' does ;)

I use 'cblock' in my later tutorials, but it's not 'the correct way', it's simply one of many correct ways - your 'MEMORY+1' is just as correct.

Personally, I find cblock the most convenient to use, as RonH obviously does.
 
Thanks for all of the information!

bsodmike, I'm just starting and I wanted to keep things as simple as possible, but I will look into using tmr0 for better delay functions, that will be a good piece of reusable code.
 
Code:
STATUS	equ 	03h
PORTA 	equ 	05h
TRISA 	equ		85h

Here's another tip

Do away with this and place this above the config line
Code:
#INCLUDE <P16F628.INC>
Also use a config line in your code, here is mine:
Code:
__CONFIG    _CP_OFF & _WDT_OFF & _HS_OSC & _LVP_OFF & _BODEN_ON & _PWRTE_ON
Not sure about the 16F628, but some of these flags may not apply to your chip, check them out, they are in the include file you just added.

where you are just starting out you can use this instead of the bsf/bcf status,5

Code:
     banksel trisa      ;go to bank 1
      movlw   b'00000000'      ;set trisa,
      movwf   TRISA         ;so all porta are outputs
      banksel   porta      ;now to bank 0

alternatively you can use a macro:

Code:
BCNT=0
BANKS	MACRO	BIT
	IF BCNT==0
	MESSG "BANKS MACRO REQUIRES ONE VARIABLE, CRUMB(TWO BITS.1-4)"
	ENDIF
BCNT++
	IF (BIT==0)
	ERRORLEVEL +302
	BCF	STATUS,RP0
	BCF	STATUS,RP1	;BANK 0
	ENDIF
	
	IF (BIT==1)
	ERRORLEVEL -302
	BSF	STATUS,RP0
	BCF	STATUS,RP1	;BANK 1
	ENDIF
	
	IF (BIT==2)
	ERRORLEVEL -302
	BCF	STATUS,RP0
	BSF	STATUS,RP1	;BANK 2
	ENDIF
	
	IF (BIT==3)
	ERRORLEVEL -302
	BSF	STATUS,RP0
	BSF	STATUS,RP1	;BANK 3
	ENDIF
	ENDM

you would use this like this

Code:
      banks 1      ;go to bank 1
      movlw   b'00000000'      ;set trisa,
      movwf   TRISA         ;so all porta are outputs
     banks 0      ;now to bank 0
the advantage of this is that you will not get any more of those annoying error 302 "Register in operand not in bank 0. Ensure that bank bits are correct." unless you actually try to access a register not in bank 0 and you are still in bank 0.

Stay tuned for more programming tips next week on this same channel....

Ron
 
:wink:

The disadvantage of using macros is that you initally have to figure out what each macro does, then keep remembering that info as you loko through the code...... This is not too bad if it's your code, but I find it confusing (getting old now!) I prefer (and it is only a personal preference) to use comments to help......

BSF STATUS,RP0 ;SWITCH TO PAGE 1

..... your code......

BCF STATUS,RP0 ;SWITCH TO PAGE 0

I think this is easier, especailly when starting out with pics, when you hit a problem (which you will!) then the code is clearer (IMHO).

I hope this helps!
 
Yes I can understnad your concern but I'd say the Banks macro is pretty self explainitory, plus I also commented it as well.

Ron
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top