機電之家資源網(wǎng)
單片機首頁|單片機基礎|單片機應用|單片機開發(fā)|單片機文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開發(fā)
培訓信息
贊助商
PIC12C509 控制LED動作程序
PIC12C509 控制LED動作程序
 更新時間:2008-7-26 16:14:08  點擊數(shù):3
【字體: 字體顏色

PIC12C509 - Getting Around the Stack Limitation

The 12C5 series PIC has only a two level stack which limits the number of nested subroutine calls to two. This may be a very serious limitation.

(The 16C84 has an eight level stack which permits nested subroutines to eight deep. I can't imagine a program where this will not be sufficient).

In the following programs an alternative user stack is presented which provides the programmer with alternative "call" and "return" capability.

Note that a user stack is implemented using the highest data address. The idea is that the user stack grows down from 1FH, while user variables are assigned from 07H and up. Thus, the degree of nesting permitted using this approach is the full variable space (25) less the number of bytes which are used as variables in the program.

There are two other limitations to this approach;

1. Only the low byte of the program counter is saved on the user stack. Thus, this limits the calling of all functions and the implementation of the functions to the same page.

However, this does not preclude one from splitting a program over several pages and implementing each called function on each page. Of course, the same implementation of functions on different pages must have different names. That is, one must be careful and think. But with the price of the 12C5XX declining to a mere $1.00 it pays to think!

This approach of splitting a program is shown in another discussion dealing with the I2C bus.

2. The FSR is used as the user defined stack pointer. Thus, if the FSR register is used elsewhere, one must be careful to save the user stack pointer in a temporary variable when using the FSR for other applications and of course, restoring it to the FSR when calls and returns are made using this approach.

Please refer to program STACK_1.ASM which continually flashes an LED on and off. Note that the main calls routines SUB1, DELAY, SUB2 and DELAY and then loops back to repeat the process.

The FSR register is intialized to the highest data location, 01FH.

Each "call" consists of the following instructions.


MOVF PCL, W ; fetch PCL to W
ADDWF OFFSET, W ; add 4
MOVWF INDF ; save to location pointed to by FSR
DECF FSR, F ; for next subroutine
GOTO SUB1 ; turn LED on

RET_POINT1:
;... continuation of program

In the above, note that the current content of the low byte of the program counter is fetched. The address to return to (RET_POINT1) is calculated by adding 4 and this is saved to the location pointed to by the user stack pointer. The stack pointer is then decremented to accommodate the next return address. Finally, a jump to the function is executed.

In the subroutine, the task is first performed. The "return" is then implemented using the following code.


; task performed
INCF FSR, F ; return
MOVF INDF, W
MOVWF PCL

In the above, the user stack pointer is incremented so as to point to the location containing the value of the program counter which was stored in the calling routine. This is fetched and placed in the low byte of the program counter. Thus, execution continues at the return point in the calling routine.


; STACK_1.ASM (12C509)
;
; Illustrates how to use user stack to implement "calls" and "returns".
; This is particularly important on the 12C509 as to stack is limited to
; two levels.
;
; Flashes LED on GPIO0, 250 ms on and 250 ms off.


LIST p=12c509
#include <p12c509.inc>
__CONFIG 1AH

LOOP1 EQU 07H ; for timing loops
LOOP2 EQU 08H
OFFSET EQU 09H

ORG 000H

MOVLW 1FH ; intitialize FSR to point to top of "stack"
MOVWF FSR

MOVLW .4
MOVWF OFFSET ; offset initialized to 4

MOVLW 1EH ; least sign bit is an output
TRIS GPIO

TOP:
; save return address on stack
MOVF PCL, W ; fetch PCL, add 4 and save at location
ADDWF OFFSET, W ; pointed to by FSR
MOVWF INDF
DECF FSR, F ; dec stack pointer for next subroutine
GOTO SUB1 ; turn LED on

MOVF PCL, W
ADDWF OFFSET, W
MOVWF INDF
DECF FSR, F
GOTO DELAY ; 250 ms delay

MOVF PCL, W
ADDWF OFFSET, W
MOVWF INDF
DECF FSR, F
GOTO SUB2 ; turn LED off

MOVF PCL, W
ADDWF OFFSET, W
MOVWF INDF
DECF FSR, F
GOTO DELAY ; 250 ms delay

GOTO TOP

SUB1:
BCF GPIO, 0 ; logic zero turns LED on

; these three lines are the equiv of a return
INCF FSR, F ; increment FSR
MOVF INDF, W ; get return address
MOVWF PCL ; and put in program counter

SUB2:
BSF GPIO, 0 ; logic one turns LED off

INCF FSR, F ; return
MOVF INDF, W
MOVWF PCL

DELAY: ; when running set LOOP1 to .250 and LOOP2 to .110.
; this will result in 250 ms delay.
MOVLW .250
MOVWF LOOP1
OUTTER:
MOVLW .110 ; close to 1.0 msec delay when set to .110
MOVWF LOOP2
INNER:
NOP
NOP
DECFSZ LOOP2, F ; decrement and leave result in LOOP2
; skip next statement if zero
GOTO INNER
DECFSZ LOOP1, F
GOTO OUTTER

INCF FSR, F ; return
MOVF INDF, W
MOVWF PCL

END

In program STACK_2.ASM, the "calls" and "returns" are implemented using macros which have been labelled as GOSUB and RET. Note that macros make the program considerably more understandable.


; STACK_2.ASM.
;
; Same as STACK_1.ASM except implemented using macros.
;
; coyright, Peter H. Anderson, MSU, June 1, '97

LIST p=12c509
#include <p12c509.inc>
__CONFIG 1AH

; Macros defined
GOSUB MACRO arg1 ; uses user defined stack to save return address
MOVF PCL, W ; and jumps to specified routine.
ADDWF OFFSET, W
MOVWF INDF
DECF FSR, F
GOTO arg1

ENDM

RET MACRO ; fetches return address from stack
INCF FSR, F
MOVF INDF, W
MOVWF PCL

ENDM

LOOP1 EQU 0CH ; for timing loops
LOOP2 EQU 0DH
OFFSET EQU 0EH

ORG 000H

MOVLW 1FH ; intitialize FSR to point to top of "stack"
MOVWF FSR

MOVLW .4
MOVWF OFFSET ; intialize OFFSET to 4

MOVLW 1EH
TRIS GPIO ; least sign bit is defined as output

TOP:
GOSUB SUB1
GOSUB DELAY
GOSUB SUB2
GOSUB DELAY

GOTO TOP

SUB1:
BCF GPIO, 0
RET
SUB2:
BSF GPIO, 0
RET

DELAY: ; when running set LOOP1 to .250 and LOOP2 to .110.
; this will result in 250 ms delay.
MOVLW .250
MOVWF LOOP1
OUTTER:
MOVLW .110 ; close to 1.0 msec delay when set to .110
MOVWF LOOP2
INNER:
NOP
NOP
DECFSZ LOOP2, F ; decrement and leave result in LOOP2
; skip next statement if zero
GOTO INNER
DECFSZ LOOP1, F
GOTO OUTTER

RET

END

  • 上一篇: PIC單片機的熱水控制器設計
  • 下一篇: PIC16F84電機速度控制程序
  • 發(fā)表評論   告訴好友   打印此文  收藏此頁  關閉窗口  返回頂部
    熱點文章
     
    推薦文章
     
    相關文章
    網(wǎng)友評論:(只顯示最新5條。)
    關于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機電之家 | 會員助手 | 免費鏈接

    點擊這里給我發(fā)消息66821730(技術支持)點擊這里給我發(fā)消息66821730(廣告投放) 點擊這里給我發(fā)消息41031197(編輯) 點擊這里給我發(fā)消息58733127(審核)
    本站提供的機電設備,機電供求等信息由機電企業(yè)自行提供,該企業(yè)負責信息內(nèi)容的真實性、準確性和合法性。
    機電之家對此不承擔任何保證責任,有侵犯您利益的地方請聯(lián)系機電之家,機電之家將及時作出處理。
    Copyright 2007 機電之家 Inc All Rights Reserved.機電之家-由機電一體化網(wǎng)更名-聲明
    電話:0571-87774297 傳真:0571-87774298
    杭州濱興科技有限公司提供技術支持

    主辦:杭州市高新區(qū)(濱江)機電一體化學會
    中國行業(yè)電子商務100強網(wǎng)站

    網(wǎng)站經(jīng)營許可證:浙B2-20080178-1