PDA

View Full Version : WORD bug



yettie
- 11th August 2005, 03:48
to all,

use of word in a for/next statement.



init:
decideInterval var WORD
TIMEINTERVAL con 600
main:
IF decideInterval = TIMEINTERVAL then
decideInterval = 0
(any code methods)
ENDIF
GOTO MAIN

END

It satisfies the IF condition unexpectedly. Changing the decideInterval type to BYTE and of course TIMEINTERVAL to max 255(or any 8Bit arbitrary value) will work correctly. Im using a PIC16F628 running 8MHz crystal oscillator. any ideas on this? thanks very much

regards,
yettie

Bruce
- 11th August 2005, 06:18
This is no BUG. Uninitialized variables will contain random values.
Try assigning a value to your word variable, and then see how it works.



init:
decideInterval var WORD
TIMEINTERVAL con 600

main:
IF decideInterval = TIMEINTERVAL then
decideInterval = 0
HIGH 0 ' LED on RB0 ----|>|---/\/\/----gnd
ELSE
decideInterval = 600
LOW 0 ' LED off
ENDIF
pause 500
GOTO MAIN

END
If your LED blinks on/off, it's working properly.

yettie
- 11th August 2005, 07:39
dear bruce,

i failed to initialized the WORD but in my program. also my bad, this is my code.



init:
decideInterval var WORD
TIMEINTERVAL con 600
decideInterval = 0

main:
decideInterval = decideInterval + 1
IF decideInterval = TIMEINTERVAL then
decideInterval = 0 ;resets the decideInteval
(a command output to LCD display)
ELSE
ENDIF
GOTO MAIN

END


i verified it that it enters the IF/THEN statement with the decideInterval = 11 or other pseudo-randomly values. sorry for the incomplete info a while ago. but this post seems to be complete now.

thanks

regards,
yettie

Bruce
- 11th August 2005, 15:20
Sorry, but I still do not understand why you think this is a bug?

With the PIC operating at 8MHz, you have an execution speed of 2 million single cycle instructions per second. That's fast..!

If you increment decideInterval on each pass through your loop, of course it will = 600 at some point. And very quickly.

Here's another example;


init:
decideInterval var WORD
TIMEINTERVAL con 600
decideInterval = 0

main:
decideInterval = decideInterval + 1
IF decideInterval = TIMEINTERVAL then
decideInterval = 0
GOTO Match
ENDIF
GOTO MAIN

Match: ' End up here in approximately 11.4mS
GOTO Match

END
From Main, through the loop once, then back to Main at 8MHz only takes around 19uS. Now take 19uS * 600 for ~11.4mS.

It takes only ~11.4mS before you increment decideInterval from 0 to 600, and then the IF/THEN statement evaluates as TRUE, and program flow jumps to Match.

Note: I verified this (PBP v2.46). It does not jump to match at 11. Only once
decideInterval = 600.

yettie
- 12th August 2005, 02:20
bruce,

to make things clear. i've written it in a program to have a 31.25ms timer at a prescale of 1:8,yielding a 250ms to overflow TIMER1. i verified it in a oscilloscope that it is accurate.



define debug_reg porta 'nevermind my serial LCD display debugger
define debug_bit 0
define debug_baud 2400
define debug_mode 1

define inthand checkNow

define OSC 8
CMCON=7

time var word
timeL var time.byte0
timeH var time.byte1
decideTimeInterval var word
TIMEINTERVAL con 600

;-----------------------
setup:
debug 12,"Starting",10,13," Program",4
pause 2000

intcon = %11000000 ;setting up gie and peie bits
time = 3036 ;calibrated to have 31.25ms scale
tmr1L = timeL ;65536 - time (preload value)
tmr1H = timeH

flag = 0

PIR1.0 = 0
PIE1.0 = 1

T1CON = %110001 ;setting up to 1:8 prescale
;31.25ms x 8 = 250ms/count
;--------------------------------
main:
if flag = 4 then ;(250ms x 4 = 1s) second ticker
flag = 0
decideTimeInterval = decideTimeInterval + 1
gosub updateTime
endif

if decideTimeInterval = TIMEINTERVAL then ;this one is the notorious routine. it's just a reset condition.
decideTimeInterval = 0 ;It resets unexpectedly. In contrast to this,
endif ;changing the decideTimeInterval to BYTE and of course
;TIMEINTERVAL <= 255 will function properly


goto main
;----------------------------
updateTime:
DEBUG "Time:",#decideTimeInterVal
return



;------------------------
;interrupt handler
@checkNow
pie1.0 = 0
flag = flag + 1
time = 3036
toggle = portb.3 ;my monitor to oscilloscope, it accurately toggles at 250ms cycle
TMR1L = timeL
TMR1H = timeH
PIR1.0 = 0
PIE1.0 = 1
resume


i hope now that everything clear for you now. the decideTimeInterval counter now increments every second avoiding fast incrementing, like you said.

any ideas?

thanks and I appreciate very much

regards,
yettie

Bruce
- 12th August 2005, 08:51
Hi Yettie,

I couldn't get your code to compile without errors. Try this;


@ DEVICE MCLR_OFF,LVP_OFF,HS_OSC,WDT_OFF
DEFINE OSC 8
define debug_reg porta 'nevermind my serial LCD display debugger
define debug_bit 0
define debug_baud 2400
define debug_mode 1

define inthand checkNow

CMCON=7
TRISB.3=0

'Variables for saving state in interrupt handler
wsave VAR BYTE $70 system ' Saves W
ssave VAR BYTE bank0 system ' Saves STATUS
psave VAR BYTE bank0 system ' Saves PCLATH
fsave VAR BYTE bank0 system ' Saves FSR
time var word
flag var byte
decideTimeInterval var word
TIMEINTERVAL con 600

;-----------------------
setup:
debug 12,"Starting",10,13," Program",4
pause 2000

intcon = %11000000 ;setting up gie and peie bits
time = 3036 ;calibrated to have 31.25ms scale
tmr1H = time.highbyte
tmr1L = time.lowbyte ;65536 - time (preload value)
flag = 0
decideTimeInterval = 0
PIR1.0 = 0
PIE1.0 = 1

T1CON = %00110001 ;setting up to 1:8 prescale
;31.25ms x 8 = 250ms/count
;--------------------------------
main:
if flag = 4 then ;(250ms x 4 = 1s) second ticker
flag = 0
decideTimeInterval = decideTimeInterval + 1
gosub updateTime
endif

if decideTimeInterval = TIMEINTERVAL then ;this one is the notorious routine. it's just a reset condition.
decideTimeInterval = 0 ;It resets unexpectedly. In contrast to this,
endif ;changing the decideTimeInterval to BYTE and of course
;TIMEINTERVAL <= 255 will function properly
goto main
;----------------------------
updateTime:
DEBUG "Time:",#decideTimeInterVal
return
;------------------------
;interrupt handler
asm
checkNow
; Save FSR, PCLATH, STATUS and W registers
movwf wsave ; Save W
swapf STATUS, W ; Swap STATUS to W (swap avoids changing STATUS)
clrf STATUS ; Clear STATUS
movwf ssave ; Save swapped STATUS
movf PCLATH, W ; Move PCLATH to W
movwf psave ; Save PCLATH

; isr routine
bsf STATUS,RP0 ; bank 1
bcf PIE1,0
bcf STATUS,RP0 ; bank 0
incf _flag,f ; increment flag
movlw 0x8
xorwf PORTB,f ; toggle portb.3
movf _time,W
movwf TMR1L
movf _time+1,W
movwf TMR1H
bcf PIR1,0
bsf STATUS,RP0 ; bank 1
bsf PIE1,0
bcf STATUS,RP0 ; bank 0

; Restore FSR, PCLATH, STATUS and W registers
movf fsave, W ; retrieve FSR value
movwf FSR ; Restore it to FSR
movf psave, W ; Retrieve PCLATH value
movwf PCLATH ; Restore it to PCLATH
swapf ssave, W ; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
movwf STATUS ; Restore it to STATUS
swapf wsave, F ; Swap the stored W value
swapf wsave, W ; Restore it to W (swap to avoid changing STATUS)
retfie ; Return from the interrupt
endasm

end
Look in the manual, and at some of the MeLabs examples for assembler interrupts to find out why it works.

yettie
- 13th August 2005, 19:35
Hi Bruce

the code is actually working to my circuit. it's just that there might have some differences in our compilers. i'm compiling it in PBP with IDE of microcode. just to study the (bug?), i'm changing the "time" variable to WORD or BYTE modifier. using the WORD seems to be not working properly other than the byte. i already prototyped this program and testing it further. I will share you further info of what more I can find out. thanks!

Regards,
Yettie