Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Code doesn't work because of a new variable

Status
Not open for further replies.

hkBattousai

Advanced Member level 4
Joined
Jun 16, 2007
Messages
118
Helped
5
Reputation
10
Reaction score
1
Trophy points
1,298
Location
Turkey
Activity points
2,182
I'm trying to run a simple program which will flash a LED.

The code which runs without any problem is :
(The led connected at port D1 blinks)
Code:
org 0						; Start code at 0

Delay1 res 1				; Reserve 1 byte for the variable Delay1
Delay2 res 1				; Reserve 1 byte for the variable Delay2

Start:
	CLRF PORTD
	CLRF TRISD
	CLRF Delay1
	CLRF Delay2

MainLoop:
	BTG PORTD,RD1			; Toggle PORT D PIN 1 (20)
Delay:
	DECFSZ Delay1,1			; Decrement Delay1 by 1, skip next instruction if Delay1 is 0
	GOTO Delay
	DECFSZ Delay2,1
	GOTO Delay
	GOTO MainLoop
end

And the erroneous code is :
(The led does not light)
Code:
org 0						; Start code at 0

Delay1 res 1				; Reserve 1 byte for the variable Delay1
Delay2 res 1				; Reserve 1 byte for the variable Delay2
Delay3 res 1

Start:
	CLRF PORTD
	CLRF TRISD
	CLRF Delay1
	CLRF Delay2
	CLRF Delay3

MainLoop:
	BTG PORTD,RD1			; Toggle PORT D PIN 1 (20)
Delay:
	DECFSZ Delay1,1			; Decrement Delay1 by 1, skip next instruction if Delay1 is 0
	GOTO Delay
	DECFSZ Delay2,1
	GOTO Delay
	DECFSZ Delay3,1
	GOTO Delay
	GOTO MainLoop
end

Why doesn't my program work when I add a third delay variable?

MCU : PIC 18F4550
IDE : MPLAB 8.10
 

Use MPLAB simulator, put some breakpoints and see exactly what's happen. It's much easier than wait for somebody to analyze the code...
 

XNOX_Rambo said:
Have you waited the entire t*256 time to see if it flashes...?
It was already too fast with two nested loops; it was flashing at about 20Hz. I waited for minutes, even left it running for an hour to see the LED flashing.
 

Is the Watchdog running?
It might be resetting the PIC before it gets a chance to flash - which you wouldn't notice with the previous fast flashing.
 

    hkBattousai

    Points: 2
    Helpful Answer Positive Rating
XNOX_Rambo said:
Is the Watchdog running?
It might be resetting the PIC before it gets a chance to flash - which you wouldn't notice with the previous fast flashing.
Hmm... That is a good point to check.
Below is my entire program code with configuration settings :

Code:
#include <P18F4550.INC>

config FOSC = HSPLL_HS ; HS with PLL enabled used by CPU and USB
config PLLDIV = 5 ; PLL prescaler 20/5=4 MHz (96MHz PLL needs
;4 MHz from prescaler)
config CPUDIV = OSC1_PLL2 ; PLL divided by 2 (96/2=48MHz) to feed CPU;
config USBDIV = 2 ; if full speed (FSEN=1) USB is fed by PLL
; divided by 2 (96/2=48MHz)
config IESO = OFF
config PWRT = OFF
config BOR = OFF
;config BORV = 2.0
config VREGEN = ON
config WDT = OFF
config WDTPS = 32768
config MCLRE = ON
config LPT1OSC = OFF
config PBADEN = OFF
config CCP2MX = ON
config STVREN = ON
config LVP = OFF
config ICPRT = OFF
config XINST = OFF
config DEBUG = OFF
config CP0 = OFF
config CP1 = OFF
config CP2 = OFF
config CPB = OFF
config CPD = OFF
config WRT0 = OFF
config WRT1 = OFF
config WRT2 = OFF
config WRT3 = OFF
config WRTB = OFF
config WRTC = OFF
config WRTD = OFF
config EBTR0 = OFF
config EBTR1 = OFF
config EBTR2 = OFF
config EBTRB = OFF

org 0						; Start code at 0


Delay1 res 1				; Reserve 1 byte for the variable Delay1
Delay2 res 1				; Reserve 1 byte for the variable Delay2
Delay3 res 1
;Delay4 res 1


Start:
	CLRF PORTD
	CLRF TRISD
	CLRF Delay1
	CLRF Delay2
	CLRF Delay3
	;CLRF Delay4


MainLoop:
	BTG PORTD,RD1			; Toggle PORT D PIN 1 (20)
Delay:
	DECFSZ Delay1,1			; Decrement Delay1 by 1, skip next instruction if Delay1 is 0
	GOTO Delay
	DECFSZ Delay2,1
	GOTO Delay
	DECFSZ Delay3,1
	GOTO Delay
	;DECFSZ Delay4,1
	;GOTO Delay
	GOTO MainLoop
end

How can I disable or modify the watchdog timer?
 

I'm not that familiar with PICs but the datasheet says:
PIC18F2455/2550/4455/4550
devices have a Watchdog Timer, which is either
permanently enabled via the Configuration bits or
software controlled (if configured as disabled).

I guess you turn it off with "config WDT = OFF" but maybe the hardware configuration overrides that?
You could try and turn off the configuration bit and see what happens.
 

XNOX_Rambo said:
I guess you turn it off with "config WDT = OFF" but maybe the hardware configuration overrides that?
You could try and turn off the configuration bit and see what happens.
I have already turned it off if you refer to my code.
I think it is something else.
 

Which compiler are you using?

I found this in the documentation for MPLAB C Compiler for PIC18 MCUs:
2.9.5.2 EXAMPLE
The following example shows how the #pragma config directive might be utilized.
The example does the following:
• Enables the Watchdog Timer,
• Sets the Watchdog Postscaler to 1:128, and
• Selects the HS oscillator

#pragma config WDT = ON, WDTPS = 128
#pragma config OSC = HS
...
void main (void)
{
...
}

Maybe you need to insert #pragma in every config line?
 

XNOX_Rambo said:
Maybe you need to insert #pragma in every config line?

I think '#pragma' directive belongs to C language only. I'm using MPLAB Assembly language. The compiler would have given an error message if I hadn't used a necessary keyword where I was obligated to.
 

If you build the program and look at the disassembly listing you will see:

0007 6A00 CLRF 0, ACCESS 54: CLRF Delay1
0009 6A01 CLRF 0x1, ACCESS 55: CLRF Delay2
000B 6A02 CLRF 0x2, ACCESS 56: CLRF Delay3

Why is the variable located at address 0 in lines 54

You defined the variables just after the org statement, that's why.

use this code after config statements:

cblock 0x20
Delay1 ; Assign an address to label Delay1
Delay2
Delay3
endc

org 0

This will define the variables at address 20

Dissasembly then shows:

0004 6A20 CLRF 0x20, ACCESS 55: CLRF Delay1
0006 6A21 CLRF 0x21, ACCESS 56: CLRF Delay2
0008 6A22 CLRF 0x22, ACCESS 57: CLRF Delay3

The program then runs with a 10 second delay.

George
 

    hkBattousai

    Points: 2
    Helpful Answer Positive Rating
Thank you geore2000, your idea solved my problem. But still I don't understand how it works with two variables defined but doesn't with three of them. Can anybody explain this to me?

Anyway, below is the final and working form of my code :

Code:
org 0x40		; Define variables at address 0x40

Delay1 res 1
Delay2 res 1
Delay3 res 1


org 0		; Place the program code at the beginning of the memory

Start:
	CLRF PORTD
	CLRF TRISD
	CLRF Delay1
	CLRF Delay2
	;CLRF Delay3
	;CLRF Delay4
	
	MOVLW 020
	MOVWF Delay3,0
	
	


MainLoop:
	BTG PORTD,RD1			; Toggle PORT D PIN 1 (20)
Delay:
	DECFSZ Delay1,1			; Decrement Delay1 by 1, skip next instruction if Delay1 is 0
	GOTO Delay
	DECFSZ Delay2,1
	GOTO Delay
	DECFSZ Delay3,1
	GOTO Delay
	MOVLW 020
	MOVWF Delay3,0
	;DECFSZ Delay4,1
	;GOTO Delay
	GOTO MainLoop
end
 

1. The MPLAB will generate 'absolute code' if only 1 asm without lkr (you cannot use Object File Directives)
2. The 'res' is used to reserve data storage or program memory (In non-relocatable code, it will be assumed to be a program memory)

In your code, the fist 2 'res' will generate 1 instruction 0xFFFF (nop). In fact, the 'Start' is located on 2, not 0. That's why it will be working.
The 3th 'res' will encourter wrong instruction decode in run time (Start at 3), but you should receive a warning for non-word aligned address.

So you can use 'cblock' as george2000's post to declare data storage as:
Code:
	org 0                  ; Start code at 0 

	cblock 0x0
	Delay1:1, Delay2:1, Delay3:1
	endc

Start:
or to treat it into relocatable code (add 18F4550.lkr) as:
Code:
	udata_acs 0x0
Delay1	res	1
Delay2	res	1
Delay3	res	1
	
	code	0x0		; Start code at 0 
Start:
FYR
 

    hkBattousai

    Points: 2
    Helpful Answer Positive Rating
The variables at the start o code space start as Hex FF

FF FF is nop so instruction is stepped over

With 3 variables you have code of
FF FF for first instruction but
FF 83 as second instruction so program tries to execute FF 83 which is as BSF instruction

The program would work again with 4 variables since it then becomes 2 Nop instructions.

This is the problem with variables in code space the chip thinks its code.

George
 

    hkBattousai

    Points: 2
    Helpful Answer Positive Rating
yager said:
In your code, the fist 2 'res' will generate 1 instruction 0xFFFF (nop). In fact, the 'Start' is located on 2, not 0. That's why it will be working.
The 3th 'res' will encourter wrong instruction decode in run time (Start at 3), but you should receive a warning for non-word aligned address.

Thank you very much. Now I completely understood my code mistake.

Even number of variable declarations at the beginning of the code will have no problem in this case. But it is not a proper way to make declarations, because the compiler would place arbitrary initial values to the variables instead of 0x00, why not.

At this point you suggest using compiler directives like "udata_acs" and "cblock".
Now correct me if I am wrong :

udata_acs is used to initialize variables in a way that we guarantee they will look like NOP instructions in the program memory. Is that true?
 

hkBattousai said:
Even number of variable declarations at the beginning of the code will have no problem in this case. But it is not a proper way to make declarations, because the compiler would place arbitrary initial values to the variables instead of 0x00, why not.
This usage is wrong. The variable declaraions should not take code space.
In fact, it just a luck. Because the reserved byte is made 0xFF, the NOP is also be 0xFXXX in PIC18.

hkBattousai said:
udata_acs is used to initialize variables in a way that we guarantee they will look like NOP instructions in the program memory. Is that true?
No. It just is a declaration, no any instruction will be inserted in program memory.
Due to MPLAB will treat it (1 asm, no lkr) into 'absolute code' (only MPASM, no MPLINK). The 'res' will reserve some space in program memory.
And it did not support Object File Directives if assembler is in absolute code operation. That's why we need use 'cblock' to declare the variables.

To let MPLAB run as relocatable code operation, you can add the lkr into the project or more asm. It will separately assemble then link them.
Now we can use Object File Directives such like as:
Code:
	access_ovr 
Delay1	res	1
Delay2	res	1
	access_ovr 
Temp1	res	1
Temp2	res	1
The link will arrange Delay1,Delay2 in Access RAM and let Temp1 = Delay1, Temp2 = Delay2 (overlay).
You can add 'label' before 'access_ovr' to manage them in your lkr and/or assign a starting address.
Code:
mytemp1	access_ovr 
Delay1	res	1
mytemp2	access_ovr 
Temp1	res	1
mytemp1	access_ovr 
Count1	res	1
The Delay1 and Temp1 will be located at different address, but Count1 is equal to Delay1.

FYR
 

    hkBattousai

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top