PIC16F627A Nested Subroutines problem
I am working on a project to control some lights, and seem to be having an issue with my nested subroutines. It seems like when I'm in one of the emergency light patterns, I call the appropriate delay subroutine, and the return opcode throws everything back to the main loop, bypassing the rest of the loop that the routine was called for. I know I haven't put in the code for pattern 1 yet, but that will be going in after I figure out this problem. (that one is going to be a lot more complex pattern). For my testing, I just have LEDs wired on port A pins 0-5, and buttons (and pulldown resistors) attached to port B pins 0-3. Is anyone here familiar with a solution to this problem? I only need to nest 2 layers deep, though 3 would be nice when I code the other light pattern (I plan on flashing the left set twice, then the right set twice, then all lights twice, like pattern 3 does once.)
movlw b'11111111' ; set port B to be inputs
movwf 86h
movlw 00h ; set port A to be outputs
movwf 85h
bcf 03h,5 ; leave config register
movlw 00h
movwf 05h
MAIN btfsc 06h,2 ; Start main loop, and check for light pattern 1/3 bit
call PTRN1 ; Jump to patern 1/3 loop
btfsc 06h,3 ; Check for light pattern 2
call PTRN2 ; Jump to pattern 2 loop
movlw 00h ; Turn off all lights
movwf 05h
btfsc 06h,0 ; check if left signal should be on
bsf 05h,0 ; turn on left signal if it should be on
btfsc 06h,1 ; check if right signal should be on
bsf 05h,1 ; turn on right signal if it should be on
goto MAIN ; restart main loop
PTRN3 movlw 05h
movwf 0Bh
movlw b'11111111' ; LIGHT PATTERN 3
movwf 05h
call SHRTDLY
start3 decfsz 0Dh
goto fin3
xorwf 05h
call SHRTDLY
goto start3
fin3 call LNGDLY
return ; Return to main loop
PTRN1
lgt1 btfsc 06h,3 ; LIGHT PATERN 1, determine if should be PATERN 3
goto PTRN3 ; Goto Patern 3 if patern bit 2 is set
return ; return to main loop.
PTRN2
lgt2 btfsc 06h,2 ; Check if should be Pattern 3
goto PTRN3
movlw b'10101010' ; Start LIGHT PATTERN 2
movwf 05h
call LNGDLY
movlw b'11111111'
movwf 05h
call LNGDLY
return ; Return to main loop
SHRTDLY movlw 7Fh
movwf 0Ah
SD2 decfsz 08h,1 ; Short delay for strobe effect
goto SD2
decfsz 09h,1
goto SD2
decfsz 0Ah,1
goto SD2
return ; return to calling loop
LNGDLY decfsz 08h,1 ; Long delay for break in flash pattern
goto LNGDLY
decfsz 09h,1
goto LNGDLY
decfsz 0Ah,1
goto LNGDLY
decfsz 0Bh,1
goto LNGDLY
return ; Return to calling loop
end
Been a while since I last worked with the PIC16, but I seem to recall that the ICE debugger environment consumes one or two stack levels (and that you are issuing CALL instructions in your routine), as well as several fixed RAM locations.
Does your code work okay if not built with debug option?
Are you managing banked RAM correctly?
I'm not using a debugger, I am making these determinations based on the behavior of it in the real pic.
I am not that familiar with banked ram, so I'm not sure if I am using it correctly. As far as I can tell, without calling the delay loops, it is functioning as expected. Since writing my original post, I attempted changing the calls from the main loops to the flash patterns to goto statements, and returning to the main loop with another goto, and it still is acting like the program is just returning to the main loop after completing the delay loops.
Erm. You should be using general purpose registers for your counters.
Using PCLATH (0Ah) as a counter is about as unwise as you can get! (The three ms bits of PCLATH are undefined)
What happens when you try to use 08h and 09h as counters is entirely undefined.
What happen when you use INTCON (0Bh) is also a bit wild.
In the end, you may find it MUCH more useful to use the built-in timer. Program loop counting is a huge waste of the chip's capabilities.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
Whatever Lau said, maybe--I don't have time to trace every register's address to its destination in your code.
Use symbolic variables if you want to be understood and not conflict with critical registers (such as INTCON or PCLATH).
Last edited by CTBill on 15 Nov 2009, 9:55 pm, edited 1 time in total.
Thank you both, I have corrected the problem. Either it was caused because I was using example code for a 16f87, or, the example code I used was a bad example. I moved my counters up to starting at 20h, and they are working much much better.
http://www.mstracey.btinternet.co.uk/pi ... ogtut5.htm
Indeed, Microchip's products started off using just a few low address registers, and gradually crept up to using lots.
The example code you linked to was probably fine for the 16f87.
Note that the example code DID give the locations symbolic names, as CTBill suggested. My preference is to see no numeric values in any code, other than maybe the odd 0, 1 or 2, say. All numeric stuff should be in include files, or at the top of the source code, as equates of one sort or another. Dredging through code to see where a particular number appears, and what it is all about, is a nightmare.
_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer
I will probably adjust my code tomorrow after I get home from work to using names for the structures. I can see how it would be easier to follow. I have a deadline of the week before christmas on this project, as it will be a gift for my dad. After I finish the microcontroller stuff, I am gonna get the transistor switches built and tested on the breadboard. Gotta get this ready to put on a real soldered board and then pot it with epoxy. Gonna leave a programming header exposed to modify it later, if need be.
