# PIC18F4 logic error?

Status
Not open for further replies.

#### Dakta

##### New Member
First post here I'm afraid, stumbled across the site when googling for header84.asm (a header file from a book im studying - pic in practice which is apparently available to download but the link doesn't work).

Anyway, I'm stuck. I know a little assembly from college so it's not my first time playing with pics, but since it's been a while (and in all fairness we didn't learn much though I worked out the seven segs on the dev boards we were given on my own which was pretty cool) I thought i'd start from the beginning. Not a bad idea because I seem to be useless now!

So I bought myself a book, development board and got a copy of mplab, all seemed to be set. So I thought i'd start by teaching myself the header included in the book. So I typed it out and after a while I hit compile - errors.

Surprisingly enough, I used my initiative and solved them on my own. I'd messed up some formatting and it now compiles.

But does it work? No. I think it's a logic error of some sort but I really can't trap it!

Basically, the header included a subroutine to cause a one second delay. I made a quick example to set the output pins on porta to high, and then call the delay before setting them back again, call the delay and repeat.

The software compiles, and runs, however it gets stuck in an endless loop in the delay subroutine. If I put a breakpoint in after I call the elay subroutine, it never gets there.

Can you see anything obvious?

Code:
; *************************************
; PIC1684 Header file
; Equates section (defining memory locations for ports etc)
; The number after 'equ' is for an internal number/address for that function
;
; Source code written by Kristian Mason, probably in 2009, all rights reserved no doubt.
;
; anyway let's declare some registers!
;

TMR0		EQU 0x01 ; timer register - oscillates at 1/4 of crystal frequency, use it with option_r to create timing loops...
STATUS		EQU	3 ; holds status of calculations and arithmetic, eg: has zero bit if calculation is absolute and carry bit if it isn't.
PORTA 		EQU	5 ; 5 bit register (0000 0) - set bits to output data (check bit for input)
PORTB		EQU	6 ; 8 bit register (0000 0000) - set bits to output data (check bit for input)
TRISA		EQU	85H ; holds the i/o values of portb pins
TRISB		EQU	86H ; holds the i/o values of porta pins eg 1111 for four input pins...
OPTION_R	EQU	81H ; 4 bit register (0000-1111) that can divide tmr0 by 2, 4, 8, 16 - 256 etc
ZEROBIT		EQU	2
COUNT		EQU	0CH ; a register to count events

;configure assembler to use pic processor
LIST P=16F84
ORG 0
GOTO START ; go to start!

; configure the pic itself
__CONFIG H'3FF0' ; hexidecimal to select LP oscillator (not power hungry, low frequency operation), WDT off, PUT on and disable code protection;

;************************
; Common subroutines - add some subroutines/code functions here to enjoy at a later line

;routine one - one second delay - assumes pic is running on a 32khz crystal.
DELAY1 	CLRF 	TMR0 ;START + clear TMR0
LOOPA  	MOVF 	TMR0,W ;READ TMR0 INTO WORKING REGISTER *YIKES!*
SUBLW 	.32 ;TIME -32
BTFSS 	STATUS,ZEROBIT
GOTO 	LOOPA
RETLW 	0
;************************

;**********************************************************
; CONFIG SECTION - TIME TO SET OUR PINS AND TIMING SETTINGS
;**********************************************************

START BSF STATUS,5 ;TURNS TO BANK1
MOVLW B'00000000' ; PUT THAT BINARY INTO WORKING REGISTER
MOVWF TRISA ;AND THEN PUT IT INTO TRISA AND NOW FOR PORTB:
MOVLW B'00000000'
MOVWF TRISB

MOVLW B'00000111' ;FOR AN UNKNOWN REASON THIS MAKES THE TIMER PRESCALER /256
MOVWF OPTION_R ; TIMER IS 1/36 SECS

BCF STATUS,5 ; RETURN TO BANK 0
CLRF PORTA ; FLUSH PORTA
CLRF PORTB ; CLEAR PORTB

; ___________________________________________________________________________________________________________________________

;*********************************************************
;*********************************************************
;*********************************************************
; WE CAN START THE PROGRAM! HURRAH!***********************
; OVER TO YOU NOW SQUIRE!*********************************
;*********************************************************
BEGIN
; set a pin on port A to high then delay
MOVLW B'00000001'
MOVWF PORTA
CALL DELAY1
; and clear port A again and repeat:
MOVLW B'00000000'
MOVWF PORTA
CALL DELAY1

GOTO BEGIN

;Call a halt to the program - let's call it a day
END

thanks
Kristian

#### colin55

##### Well-Known Member
Create you own delay sub-routine by decrementing a couple of registers.
See if this fixes the problem.

#### Mr RB

##### Well-Known Member
With a 32kHz xtal and TMR0 at 1:256 prescaler you can generate a 1 second delay after 32 counts of TMR0. Your delay routine is trying to do the right thing but is a bit clumsy.
You can simplify it a lot and improve its reliability by changing it to this;

Code:
;routine one - one second delay - assumes pic is running on a 32khz crystal.
DELAY1 	CLRF 	TMR0        ;START + clear TMR0
LOOPA   BTFSS 	TMR0,5      ; bit 5 is set when TMR0 >= 32
GOTO 	LOOPA
RETLW 	0
;************************

Having said that i think the problem might be in your manual declaration of register addresses at the start. Try using the #include "16F84".h etc so MPLAB sets up the register names and addresses for you.

#### Dakta

##### New Member
I appreciate the reply, but was thrown a bit out of my depth! (sorry didnt catch your second reply, i'l try that asap)

Anyway, just spent a good ten minutes trying to use my iniative, looked up the datasheet, found a GPR well out of harms way and threw this together in place of the loop subroutine above:

Code:
;kris's subroutine
KrisDelay	clrf 0x0C
LOOPB       movlw b'00000000'
incf 0x0C
btfss 0x0C,b'00000010'
GOTO LOOPB
RETLW	0

It is not neat. But it works. Third time around, when the 7th rightmost bit is set to high she breaks out of the loop as she should.

Last edited:

#### Dakta

##### New Member
With a 32kHz xtal and TMR0 at 1:256 prescaler you can generate a 1 second delay after 32 counts of TMR0. Your delay routine is trying to do the right thing but is a bit clumsy.
You can simplify it a lot and improve its reliability by changing it to this;

Code:
;routine one - one second delay - assumes pic is running on a 32khz crystal.
DELAY1 	CLRF 	TMR0        ;START + clear TMR0
LOOPA   BTFSS 	TMR0,5      ; bit 5 is set when TMR0 >= 32
GOTO 	LOOPA
RETLW 	0
;************************

Having said that i think the problem might be in your manual declaration of register addresses at the start. Try using the #include "16F84".h etc so MPLAB sets up the register names and addresses for you.

Unfortunately your snippet sticks itself in an endless loop...

weird, eh? I can't see anything logically incorrect in either of our methods. In addition to this, I also tried calling the 1684 file, which also compiled succesfully after removing my manual calls, however the loop was once again endless.

Last edited:

#### Mr RB

##### Well-Known Member
That pretty much proves it's a setup issue.

Both my loop code and yours should work, the only thing common to both must be some setup issue like TMR0 is not setup right etc. I think your initialisation code is funky. Try using the proper include file for that PIC that has all the register names correctly declared, instead of declaring them yourself.

#### Dakta

##### New Member
I just replaced this:

TMR0 EQU 0x01 ; timer register - oscillates at 1/4 of crystal frequency, use it with option_r to create timing loops...
STATUS EQU 3 ; holds status of calculations and arithmetic, eg: has zero bit if calculation is absolute and carry bit if it isn't.
PORTA EQU 5 ; 5 bit register (0000 0) - set bits to output data (check bit for input)
PORTB EQU 6 ; 8 bit register (0000 0000) - set bits to output data (check bit for input)
TRISA EQU 85H ; holds the i/o values of portb pins
TRISB EQU 86H ; holds the i/o values of porta pins eg 1111 for four input pins...
OPTION_R EQU 81H ; 4 bit register (0000-1111) that can divide tmr0 by 2, 4, 8, 16 - 256 etc
ZEROBIT EQU 2
COUNT EQU 0CH ; a register to count events

with this:

#include <p16f84.inc>
OPTION_R EQU 81H ; 4 bit register (0000-1111) that can divide tmr0 by 2, 4, 8, 16 - 256 etc
ZEROBIT EQU 2
COUNT EQU 0CH ; a register to count events

Still no luck - thanks for sticking with me, do you think it could be a config problem with mplab?

#### mvs sarma

##### Well-Known Member
I just replaced this:
.......a config problem with mplab?
Instead, if you use
Code:
    #include    <p16F84A.inc>
you could avoid defining most common parameters in 16F84A
please see this should work as it worked on MPLAB sim with the delay time reduced to -2 instead of -32 to reduce wait time.
Code:
; *************************************
; PIC1684 Header file
; Equates section (defining memory locations for ports etc)
; The number after 'equ' is for an internal number/address for that function
;
; Source code written by Kristian Mason, probably in 2009, all rights reserved no doubt.
;
; anyway let's declare some registers!
;

LIST P=16F84A
#include	<p16F84A.inc>
errorlevel	-302
ZEROBIT		EQU	2
COUNT		EQU	0CH ; a register to count events

;configure assembler to use pic processor

ORG 0
GOTO START ; go to start!

; configure the pic itself
__CONFIG H'3FF0' ; hexidecimal to select LP oscillator (not power hungry, low frequency operation), WDT off, PUT on and disable code protection;

;************************
; Common subroutines - add some subroutines/code functions here to enjoy at a later line

;routine one - one second delay - assumes pic is running on a 32khz crystal.
DELAY1 	CLRF 	TMR0 ;START + clear TMR0
LOOPA  	MOVF 	TMR0,W ;READ TMR0 INTO WORKING REGISTER *YIKES!*
SUBLW 	.32 ;TIME -32
BTFSS 	STATUS,ZEROBIT
GOTO 	LOOPA
RETLW 	0
;************************

;**********************************************************
; CONFIG SECTION - TIME TO SET OUR PINS AND TIMING SETTINGS
;**********************************************************

START BSF STATUS,5 ;TURNS TO BANK1
MOVLW B'00000000' ; PUT THAT BINARY INTO WORKING REGISTER
MOVWF TRISA ;AND THEN PUT IT INTO TRISA AND NOW FOR PORTB:
MOVLW B'00000000'
MOVWF TRISB

MOVLW B'00000111' ;FOR AN UNKNOWN REASON THIS MAKES THE TIMER PRESCALER /256
MOVWF OPTION_REG ; TIMER IS 1/36 SECS

BCF STATUS,5 ; RETURN TO BANK 0
CLRF PORTA ; FLUSH PORTA
CLRF PORTB ; CLEAR PORTB

; ___________________________________________________________________________________________________________________________

;*********************************************************
;*********************************************************
;*********************************************************
; WE CAN START THE PROGRAM! HURRAH!***********************
; OVER TO YOU NOW SQUIRE!*********************************
;*********************************************************
BEGIN
; set a pin on port A to high then delay
MOVLW B'00000001'
MOVWF PORTA
CALL DELAY1
; and clear port A again and repeat:
MOVLW B'00000000'
MOVWF PORTA
CALL DELAY1

GOTO BEGIN

;Call a halt to the program - let's call it a day
END

the missing equates are no more needed
OPTION_R is not correct and it is "OPTION_REG"

#### Attachments

• dackta.zip
6.6 KB · Views: 46
Last edited:

#### Dakta

##### New Member
You're going to hate me, but it still loops forever!

I don't blame your coding, or mine - i've triple checked the book, your modifications are different route to the same problem but both should work - I think it must be mplab or my computer. :|

#### mvs sarma

##### Well-Known Member
You're going to hate me, but it still loops forever!

I don't blame your coding, or mine - i've triple checked the book, your modifications are different route to the same problem but both should work - I think it must be mplab or my computer. :|
LoL, no way to laugh at a person learning ,
I myself am a learner at my 64+ . i have practically checked it on MPLAB simulator, and the port A bit 0 changes state.

by the way, how did you check?
did you program the chip and it did not behave?
because, simulator check will take very long time and you feel it is locked up.
to avoid that situation, what I did, i changed the delay value from the present .32 to .2, compiled , ran simulator and after satisfying only i restored the value .32.
i don't of course certify the delay routine's accuracy with .32 as the delay value.
can you do the same, and then run simulator?
now I am attaching the modded file with a delay value of .2 in the line
sublw .2

please use the .asm file, compile and run simulator
it still takes more time as simulator is not real world
so be patient and watch the port a by opening the special function registers
also you may watch TMR0
clearing and incrementing one by one to 2 and port A changes state.

#### Attachments

• daktanew.zip
6.6 KB · Views: 47
Last edited:

#### Dakta

##### New Member
I don't have my dev board with me at the moment, so I'm setting a breakpoint immiediately after the delay call (in the main code) in the hope I get it flagged, I've taken your advice and chaged '32' to '1' and '2' in turn, stepped through the loop line by line for more than the set number of iterations, and it still seems to continue.

Finally, I thought i'd simulate it on Isis, however whilst I get the pin on porta to set high and light a virtual led, it never clears as it's getting stuck in the loop after that point.

I was expecting when I first posted to have an obvious error pointed out - I don't know whether i'm glad or not that it hasn't happened!

#### mvs sarma

##### Well-Known Member
I don't have my dev board with me at the moment, so I'm setting a breakpoint immiediately after the delay call (in the main code) in the hope I get it flagged, I've taken your advice and chaged '32' to '1' and '2' in turn, stepped through the loop line by line for more than the set number of iterations, and it still seems to continue.

Finally, I thought i'd simulate it on Isis, however whilst I get the pin on porta to set high and light a virtual led, it never clears as it's getting stuck in the loop after that point.

I was expecting when I first posted to have an obvious error pointed out - I don't know whether i'm glad or not that it hasn't happened!
i have mean time modded my earlier post
please read again Dakta ! it might take 2 minutes with .2 inas the value, on simulator of MPLAB

Last edited:

#### Dakta

##### New Member
Thanks, got there in the end!

Not totally sure what the problem was, maybe I just wasn't being patient enough?

#### mvs sarma

##### Well-Known Member
Thanks, got there in the end!

Not totally sure what the problem was, maybe I just wasn't being patient enough?
you can replace back.32 if you want
program the chip and test on breadboard

there is one program called picloops
it can give you delay subroutines see here https://www.biltronix.com/picloops.html

you can use it before you practice delay loops

all the best

Last edited:

#### Dakta

##### New Member
thanks for that, touch wood can get started now!

Status
Not open for further replies.

Replies
3
Views
3K
Replies
8
Views
3K
Replies
6
Views
2K
Replies
1
Views
901
Replies
24
Views
5K