Pausa en ASM

Hola a todos, vengo con una duda un poquitin urgente..
Y se que es algo muy sencillo, necesito pausar un programa, mediante un pulsador conectado en la pata 10 u 11 en un PIC16F84, el código sobre el que estoy trabajando es el siguiente:

Código:
;-------------------------------------------------------------------------
;                             Darkroom Timer                              
;               April '99  Stan Ockers (ockers@anl.gov)                   
;             Modified by Vassilis Papanikolaou, April '05                                         
;                                                                         
;       Counts down from 0-99 min and 0-59 sec giving an alarm at 0       
;     initial counts are held in data EEPROM setable with one button      
;                                                                         
;  RBO-RB3 to bases of transistors connect to common cathode of displays. 
;  RA0-RA3 to 1,2,4,8 BCD inputs of CD4511 7 segment latch and driver.    
;  RB7 to start pushbutton used to start countdown and silence alarm.     
;  RB6 goes to time set pushbutton use to sucessively set the digits.     
;  RA4 with pull-up resistor goes to PB to select from 15 starting counts 
;  RB4 goes to Dot Points												  
;  RB5 goes to Relay								                      
;-------------------------------------------------------------------------

	PROCESSOR   PIC16F84A									; PIC type
    #INCLUDE	"P16f84A.INC"								; Include file
	__CONFIG 	_XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF	; Fuses
	ERRORLEVEL 	-302    									; No bank warnings

;-------------------------------------------------------------------------
;    Here we define our own personal registers and give them names        
;-------------------------------------------------------------------------

SEC       	EQU H'0C'          ; this register holds the value of seconds
SEC10     	EQU H'0D'          ; holds value of 10's of seconds
MIN      	EQU H'0E'          ; holds value of minutes
MIN10     	EQU H'0F'          ; holds value of 10's of minutes
DIGCTR    	EQU H'10'          ; 8 bit counter, only 2 lowest bits actually used
DIGIT     	EQU H'11'          ; hold digit number to access table
INTCNT    	EQU H'12'          ; counts # interrupts to determine when 1 sec up
FUDGE     	EQU H'13'          ; allows slight adjustment every 7 interrupts
RUNFLG    	EQU H'14'          ; bit 0 only, tells if countdown in progress 
W_TEMP    	EQU H'15'          ; temporarily holds value of W
STATUS_TEMP EQU H'16'   	   ; temporarily holds value of STATUS
SECNT     	EQU H'17'          ; used in counting 25, 20 msec delays for 1 sec
CNTMSEC   	EQU H'18'          ; used in timing of milliseconds
ALARM     	EQU H'19'          ; bit 0 only, used as flag for when to alarm
OFFSET    	EQU H'1A'          ; hold offset of address in EEPROM
KEEP        EQU H'1B'		   ; hold RB4 and RB5 state

;-------------------------------------------------------------------------
;    Here we give names to some numbers to make their use more clear      
;-------------------------------------------------------------------------

   #DEFINE   START_PB  D'7'
   #DEFINE   SET_PB    D'6'
   #DEFINE   SELECT_PB D'4'

   #DEFINE   RB0       D'0'
   #DEFINE   RB1       D'1'
   #DEFINE   RB2       D'2'
   #DEFINE   RB3       D'3'
   #DEFINE   RB4       D'4'
   #DEFINE   RB5       D'5'

;-------------------------------------------------------------------------
;         We set the start of code to orginate a location zero            
;-------------------------------------------------------------------------

      ORG 0

            GoTo MAIN                  ; jump to the main routine
            NOP                        
            NOP                        
            NOP                        
            GoTo INTERRUPT             ; interrupt routine

;-------------------------------------------------------------------------
;    This table is used to get a bit pattern that will turn on a digit    
;-------------------------------------------------------------------------

BITPAT      ADDWF PCL,f                ; get bit pattern for transistors
            RETLW H'0E'                ; a low, (0), turns the transistor on  
            RETLW H'0D'                  
            RETLW H'0B'                  
            RETLW H'07'                  

;-------------------------------------------------------------------------
;          Initialization routine sets up ports and timer                 
;-------------------------------------------------------------------------

INIT        MOVLW H'C0'                ; PB6 & PB7 inputs all others outputs
            TRIS PORTB                 
            MOVLW H'10'                ; Port RA4 input, others outputs
            TRIS PORTA                 
            MOVLW H'03'                ; prescaler on TMR0 and 1:16
            OPTION                     
            MOVLW H'A0'                ; GIE & T0IE set T0IF cleared
            MOVWF INTCON               
            MOVLW H'F4'                ; initialize INTCNT
            MOVWF INTCNT               
            MOVLW H'06'                ; initialize FUDGE
            MOVWF FUDGE                
            CLRF OFFSET                ; initialize OFFSET
            Return                     

;-------------------------------------------------------------------------
;   This is the interrupt routine that is jumped to when TMR0 overflows   
;-------------------------------------------------------------------------

INTERRUPT   MOVWF W_TEMP               ; save W
            SWAPF STATUS,W             ; save status
            MOVWF STATUS_TEMP          ; without changing flags
            ;-------------------------------------------------------------
            MOVF PORTB,W			   ; save PORTB
            ANDLW H'30'				   ; mask out unwanted bits	
			MOVWF KEEP				   ; save RB4 and RB5
            ;-------------------------------------------------------------
            INCF DIGCTR,f              ; next digit #
            MOVF DIGCTR,W              ; get it into W
            ANDLW H'03'                ; mask off 2 lowest bits
            MOVWF DIGIT                ; save it for later
            ADDLW H'0C'                ; point at register to display
            MOVWF FSR                  ; use as pointer
            MOVF INDF,W                ; get value of reg pointed to into W
            MOVWF PORTA                ; output to CD4511
            MOVF DIGIT,W               ; recall digit #
            Call BITPAT                ; get bit pattern
			;-------------------------------------------------------------
            IORWF KEEP,W      		   ; restore RB4 and RB5
			MOVWF PORTB                ; select transistor
			;-------------------------------------------------------------
            DECFSZ INTCNT,f            ; finished 1 sec ?
            GoTo RESTORE               ; not yet, return and enable inter.
            Call EVERYSEC              ; go to every second routine
            MOVLW H'F4'                ; reset INTCNT to normal value
            MOVWF INTCNT               
            DECFSZ FUDGE,f             ; time for fudge?
            GoTo RESTORE               ; not yet, continue on
            MOVLW H'06'                ; reset FUDGE to 6
            MOVWF FUDGE                
            INCF INTCNT,f              ; INTCNT to 245
RESTORE     SWAPF STATUS_TEMP,W        ; get original status back
            MOVWF STATUS               ; into status register
            SWAPF STATUS_TEMP,f        ; old no flags trick again
            SWAPF STATUS_TEMP,W        ; to restore W
            BCF INTCON,T0IF            ; clear the TMR0 interrupt flag
            RETFIE                     ; finished

;-------------------------------------------------------------------------
;       This routine is called by the interrupt routine every second      
;-------------------------------------------------------------------------

EVERYSEC    BTFSS RUNFLG,0             ; return if runflg not set
            Return   
			;-------------------------------------------------------------            
            MOVLW  1 << 4      		   
  			XORWF  PORTB, f			   ; Toggle DPs
			;-------------------------------------------------------------            
            DECF SEC,f                 ; decrement seconds digit
            INCFSZ SEC,W               ; test for underflow
            GoTo CKZERO                
            MOVLW H'09'                ; reset sec to 9
            MOVWF SEC                  
            DECF SEC10,f               ; decrement SEC10
            INCFSZ SEC10,W             ; check underflow
            GoTo CKZERO                
            MOVLW H'05'                  
            MOVWF SEC10                
            DECF MIN,f                 
            INCFSZ MIN,W               
            GoTo CKZERO                
            MOVLW H'09'              
            MOVWF MIN                  
            DECF MIN10,f               
CKZERO      MOVF SEC,f                 ; test SEC for zero
            BTFSS STATUS,Z             
            Return                     
            MOVF SEC10,f               ; check SEC10 for zero
            BTFSS STATUS,Z             
            Return                     
            MOVF MIN,f                 ; check MIN for zero
            BTFSS STATUS,Z             
            Return                     
            MOVF MIN10,f               ; check MIN10 for zero
            BTFSS STATUS,Z             
            Return                     
            CLRF RUNFLG                ; stop the countdown
            BSF ALARM, 0               ; set the alarm flag
            Return                     

;-------------------------------------------------------------------------
;          This is a routine to read a byte from the data EEPROM          
;-------------------------------------------------------------------------

READEE      MOVWF EEADR                ; set up eeprom address from W
            BSF STATUS,RP0             ; change to page 1
            BSF EECON1,RD              ; set the read bit
            BCF STATUS,RP0             ; back to page 0
            MOVF EEDATA,W              ; return value in W
            Return                     

;-------------------------------------------------------------------------
;         This routine fills the display registers from data EEPROM       
;-------------------------------------------------------------------------

GETEE       MOVLW H'01'                ; EEprom location 1 +
            ADDWF OFFSET,W             ; offset from start 
            Call READEE                ; into W
            MOVWF SEC                  ; into SEC register
            MOVLW H'02'                ; location 2 +
            ADDWF OFFSET,W             ; offset from start 
            Call READEE                ; into W
            MOVWF SEC10                ; into SEC10 register
            MOVLW H'03'                ; location 3 +
            ADDWF OFFSET,W             ; offset from start 
            Call READEE                ; into W
            MOVWF MIN                  ; into MIN register
            MOVLW H'04'                ; location 4 +
            ADDWF OFFSET,W             ; offset from start 
            Call READEE                ; into W
            MOVWF MIN10                ; into MIN10 register
            Return                     

;-------------------------------------------------------------------------
;              This routine writes a byte to data EEPROM                  
;-------------------------------------------------------------------------

WRITEEE     BSF STATUS,RP0             ; set up EEADR and EEDATA first
            CLRF EECON1                
            BSF EECON1,WREN            ; enable write
            MOVLW H'55'                ; magic sequence
            MOVWF EECON2               
            MOVLW H'AA'                  
            MOVWF EECON2               
            BSF EECON1,WR              
EELOOP      BTFSC EECON1,WR            ; wait for WR to go low
            GoTo EELOOP                ; not yet
            BSF EECON1,WREN            
            BCF EECON1,EEIF            ; clear the interrupt flag
            BCF STATUS,RP0             ; return to page 0
            Return                     

;-------------------------------------------------------------------------
;         This routine puts display registers into data EEPROM            
;-------------------------------------------------------------------------

PUTEE       MOVF SEC,W                 ; put digit registers into EEprom
            MOVWF EEDATA               
            MOVLW H'01'                ; EEPROM location 1 +  
            ADDWF OFFSET,W             ; offset from start 
            MOVWF EEADR                
            Call WRITEEE               
            MOVF SEC10,W               
            MOVWF EEDATA               
            MOVLW H'02'                ; EEPROM location 2 +  
            ADDWF OFFSET,W             ; offset from start 
            MOVWF EEADR                
            Call WRITEEE               
            MOVF MIN,W                 
            MOVWF EEDATA               
            MOVLW H'03'                ; EEPROM location 3 +  
            ADDWF OFFSET,W             ; offset from start 
            MOVWF EEADR                
            Call WRITEEE               
            MOVF MIN10,W               
            MOVWF EEDATA               
            MOVLW H'04'                ; EEPROM location 4 +  
            ADDWF OFFSET,W             ; offset from start 
            MOVWF EEADR                
            Call WRITEEE               
            Return                     

;-------------------------------------------------------------------------
;         This is the main routine, the program starts here               
;-------------------------------------------------------------------------

MAIN        Call INIT                  ; set up ports etc.

;-------------------------------------------------------------------------
;           We will return to this point when alarm is shut off.          
;-------------------------------------------------------------------------

EE2D        Call GETEE                 ; put eeprom in display regs.
            BCF RUNFLG, 0              ; clear run flag so no countdown
            BCF ALARM, 0               ; clear alarm flag
			;-------------------------------------------------------------
            BCF PORTB,RB5              ; turn RELAY OFF    
            BSF PORTB,RB4              ; turn DPs ON
			;-------------------------------------------------------------
            Call WAITSTARTUP           ; wait till no switches pressed
            Call WAITSETUP
            Call WAITSELECT

;-------------------------------------------------------------------------
;      This loop checks for either pushbutton and acts  accordingly       
;-------------------------------------------------------------------------

KEYCHKLOOP  BTFSS PORTB,START_PB       ; check for start pressed
            GoTo STARTCNT              ; yes, start count
            BTFSS PORTB,SET_PB         ; check for set pressed
            GoTo SETDISP               ; yes, set display
            BTFSS PORTA,SELECT_PB      ; check select pushbutton pressed
            GoTo SETSELECT             ; yes, select starting count
            GoTo KEYCHKLOOP            ; loop to catch key press

;-------------------------------------------------------------------------
;    If start key has been pressed then start countdown process,          
;    I initially released this code with only the setting of the          
;    run flag included.  If you think about it you must also reset        
;    TMR0 to zero.  TMR0 is free running and could have any value         
;    0-255 when the button in pressed. Also INTCNT has to be              
;    initialized because the previous count could have been cancelled.    
;-------------------------------------------------------------------------

STARTCNT    Call WAITSTARTUP           ; wait for release of start key
            MOVLW D'244'               ; reset INTCNT
            MOVWF INTCNT
            CLRF TMR0                  ; and clear timer 0 
			;-------------------------------------------------------------
            BSF PORTB,RB5              ; turn RELAY ON  
 			;-------------------------------------------------------------
            BSF RUNFLG, 0              ; start the countdown

;-------------------------------------------------------------------------
;        Once started just loop looking for cancel or reaching 0000       
;-------------------------------------------------------------------------

MAINLOOP    BTFSS PORTB,START_PB       ; countdown in progress, check start
            GoTo EE2D                  ; start over again if pressed
            BTFSC ALARM, 0             ; reached 0000 yet?       
            GoTo RELAYOFF              ; yes, turn RELAY OFF
            GoTo MAINLOOP              ; no start switch, continue looping

;-------------------------------------------------------------------------
;    This code sounds the alarm and waits on start to be pressed          
;-------------------------------------------------------------------------

RELAYOFF
FINALWAIT   ;-------------------------------------------------------------
		    BCF PORTB,RB5              ; turn RELAY OFF
            BSF PORTB,RB4              ; turn DPs ON
			;-------------------------------------------------------------
            BTFSC PORTB,START_PB       ; start button pressed
            GoTo  FINALWAIT            ; not yet
            Call DLY20                 ; debounce just to make sure
            BTFSC PORTB,START_PB       ; second look
            GoTo FINALWAIT             ; nah, keep waiting
            Call WAITSTARTUP           ; now wait for the switch up
            GoTo EE2D                  ; start all over again

;-------------------------------------------------------------------------
;                    Wait for release of start button                     
;-------------------------------------------------------------------------

WAITSTARTUP BTFSS PORTB,START_PB       ; wait for release
            GoTo WAITSTARTUP           ; not released yet
            Call DLY20                 ; debounce release 
            BTFSS PORTB,START_PB       ; 2nd check, make sure released
            GoTo WAITSTARTUP           ; keep checking
            Return

;-------------------------------------------------------------------------
;                    Wait for release of set button                       
;-------------------------------------------------------------------------

WAITSETUP   BTFSS PORTB,SET_PB         ; wait for release
            GoTo WAITSETUP             ; not yet
            Call DLY20                 ; debounce release 
            BTFSS PORTB,SET_PB         ; 2nd check, make sure released
            GoTo WAITSETUP             ; keep checking
            Return

;-------------------------------------------------------------------------
;                    Wait for release of select button                    
;-------------------------------------------------------------------------

WAITSELECT  BTFSS PORTA,SELECT_PB      ; wait for release
            GoTo WAITSELECT            ; not yet
            Call DLY20                 ; debounce release 
            BTFSS PORTA,SELECT_PB      ; 2nd check, make sure released
            GoTo WAITSELECT            ; keep checking
            Return

;-------------------------------------------------------------------------
;       Routine to follow sets the countdown time digit by digit          
;-------------------------------------------------------------------------

SETDISP     Call WAITSETUP             ; wait for set key to be released
            MOVLW H'0A'                ; put A's in digits, (no display)
            MOVWF MIN10                ; 10's of minutes
            MOVWF MIN                  ; minutes
            MOVWF SEC10                ; 10's of seconds
            MOVWF SEC                  ; seconds
STARTMIN10  CLRF  MIN10                ; 0 now in MIN10
MOREMIN10   MOVLW H'19'                ; 25 delays of 20 msec
            MOVWF SECNT                ; into counting register
WAIT1       Call DLY20                 
            BTFSS PORTB,SET_PB         ; set key pressed?
            GoTo MINSET                ; yes MIN10 now set
            DECFSZ  SECNT,f            ; finished 1 sec delay?
            GoTo WAIT1                 ; continue wait
            INCF MIN10,f               ; every second increment 10's MIN
            MOVLW H'0A'                ; reached 10?
            SUBWF MIN10,W              
            BTFSC STATUS,Z             ; Z set if reached 10
            GoTo STARTMIN10            ; start again with 0
            GoTo MOREMIN10             ; set up another 1 sec delay
MINSET      Call WAITSETUP             ; wait for release of set key
STARTMIN    CLRF MIN                   ; 0 into MIN
MOREMIN     MOVLW H'19'                ; 25 delays of 20 msec
            MOVWF SECNT                ; into counting register
WAIT2       Call DLY20                 
            BTFSS PORTB,SET_PB         ; set pressed?
            GoTo SETSEC10              ; yes, finished with MIN
            DECFSZ SECNT,f             ; finished 1 sec delay?
            GoTo WAIT2                 ; continue wait
            INCF MIN,f                 ; every second increment MIN
            MOVLW H'0A'                ; reached 10?
            SUBWF MIN,W              
            BTFSC STATUS,Z             ; Z set if reached 10
            GoTo STARTMIN              ; put zero in if Z set
            GoTo MOREMIN               ; set up another 1 sec delay
SETSEC10    Call WAITSETUP             ; wait release
STARTSEC10  CLRF SEC10                 ; 0 into SEC10
MORESEC10   MOVLW H'19'                ; 25 delays of 20 msec
            MOVWF SECNT                ; into counting register
WAIT3       Call DLY20                 
            BTFSS PORTB,SET_PB         ; set pressed?
            GoTo  SETSEC               ; yes quit incrementing
            DECFSZ SECNT,f             ; finished 1 sec delay?
            GoTo WAIT3                 ; continue wait
            INCF SEC10,f               ; every second increment 10's SEC
            MOVLW H'06'                ; reached 6?
            SUBWF SEC10,W              
            BTFSC STATUS,Z             ; Z set if reached 6
            GoTo STARTSEC10            ; put zero in if Z set
            GoTo MORESEC10             ; set up another 1 sec delay
SETSEC      Call WAITSETUP             ; wait for release
STARTSEC    CLRF SEC                   ; 0 into SEC
MORESEC     MOVLW H'19'                ; 25 delays of 20 msec
            MOVWF SECNT                ; into counting register
WAIT4       Call DLY20                 
            BTFSS PORTB,SET_PB         ; set button pressed?
            GoTo  FINSET               ; yes finished setting digits
            DECFSZ SECNT,f             ; finished 1 sec delay?
            GoTo WAIT4                 ; continue wait
            INCF SEC,f                 ; every second increment SEC
            MOVLW H'0A'                ; reached 10?
            SUBWF SEC,W              
            BTFSC STATUS,Z             ; Z set if reached 10
            GoTo STARTSEC              ; put zero in if Z set
            GoTo MORESEC               ; set up another 1 sec delay
FINSET      BCF INTCON, GIE            ; disable interrupts
            Call PUTEE                 ; put new digits into EEPROM
            BSF INTCON, GIE            ; re-enable interrupts
            Call WAITSETUP             ; make sure set switch up
            GoTo KEYCHKLOOP            ; start checking buttons again

;-------------------------------------------------------------------------
;        Selects starting count by changing EEPROM location 0             
;-------------------------------------------------------------------------

SETSELECT   MOVLW D'4'                 ; offset up 4
            ADDWF OFFSET,F             ; next offset position
            MOVLW D'60'                ; reached 16th yet?
            SUBWF OFFSET,W             ; will give zero if yes
            BTFSC STATUS,Z             ; skip if not 64
            CLRF  OFFSET               ; reset position to zero
            MOVLW 0                    ; EEPROM location
            MOVWF EEADR                ; set up address
            MOVF OFFSET,W              ; offset # into W
            MOVWF EEDATA               ; set up data
            BCF INTCON,GIE             ;  clear GIE, disable interrupts
            Call WRITEEE               ; save # in location 0
            BSF INTCON,GIE             ; re-enable interrupts
            Call GETEE                 ; get new start count into display
            Call WAITSELECT            ; make sure select switch is up
            GoTo KEYCHKLOOP            ; start checking buttons again

;-------------------------------------------------------------------------
;  The following are various delay routines based on instruction length.    
;  The instruction length is assumed to be 1 microsecond (4Mhz crystal).  
;-------------------------------------------------------------------------

DLY20       MOVLW 20                   ; delay for 20 milliseconds

; N millisecond delay routine 

NMSEC       MOVWF CNTMSEC              ; delay for N (in W) milliseconds
MSECLOOP    MOVLW D'248'               ; load takes 1 microsec
            Call MICRO4                ; by itself CALL takes ...
                                       ; 2 + 247 X 4 + 3 + 2 = 995
            NOP                        ; 1 more microsec 
            DECFSZ CNTMSEC,f           ; 1 when skip not taken, else 2
            GoTo MSECLOOP              ; 2 here: total 1000 per msecloop
            Return                     ; final time through takes 999 to here
                                       ; overhead in and out ignored

; 1 millisecond delay routine 

ONEMSEC     MOVLW D'249'               ; 1 microsec for load W
                                       ; loops below take 248 X 4 + 3 = 995
MICRO4      ADDLW H'FF'                ; subtract 1 from 'W'
            BTFSS STATUS,Z             ; skip when you reach zero
            GoTo MICRO4                ; loops takes 4 microsec, 3 for last
            Return                     ; takes 2 microsec
                                       ; call + load  W + loops + return =
                                       ; 2 + 1 + 995 + 2 = 1000 microsec

;-------------------------------------------------------------------------
;    Here we set up the initial values of the digits in data EEPROM       
;-------------------------------------------------------------------------
           
		  ORG H'2100'

          DE 0, 0, 3, 0, 0      ; 1st starting #
          DE    0, 0, 1, 0      ; 2nd starting #
          DE    0, 0, 2, 0      ; 3rd starting #
          DE    0, 0, 3, 0      ; 4th starting #
          DE    0, 0, 4, 0      ; 5th starting #
          DE    0, 0, 5, 0      ; 6th starting #
          DE    0, 0, 6, 0      ; 7th starting #
          DE    0, 0, 7, 0      ; 8th starting #
          DE    0, 0, 8, 0      ; 9th starting #
          DE    0, 0, 9, 0      ; 10th starting #
          DE    0, 0, 0, 1      ; 11th starting #
          DE    0, 0, 0, 2      ; 12th starting #
          DE    0, 0, 0, 3      ; 13th starting #
          DE    0, 0, 0, 4      ; 14th starting #
          DE    0, 0, 0, 5      ; 15th starting #

          END

La idea es que el oprimiendo un pulsador se pause todo, y se quede en los displays visualizandose el número que estaba antes de pausarse, y que cuando se vuelva a oprimir, o se oprima otro botón (me quedan dos lugares disponibles, la pata 10 y la 11) se largue de vuelta el tiempo.

Como ven es un temporizador, pero falta la opción de pausa, y sinceramente me doy muy poca idea en ASM para hacerlo yo mismo, si alguien pudiera colaborarme, estaría muy agradecido

Muchas gracias por su tiempo

Saludos!
 
Atrás
Arriba