Interrupt for a PIC16F877A

Status
Not open for further replies.

triplestak

New Member
Hey guys,

I have this program in assembly language that I did through MPLABIDE, but my goal is to get the RB0 to be the control Interrupt that makes the count (to 10) output to the LED (PORTA). I have it backwards. The count, automatically starts on the LEDS and when I press RB0 the count is interrupted or "paused" if you will. It continues when I let go. Does anyone have any suggestions to help me reverse this so that RB0 makes the count increment, and when I release it, the count pauses?

Code:
processor      16f877a
include <p16f877a.inc>

__config       _RC_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF &_LVP_OFF

;Set User ID Memory

;__idlocs        0x1234


org 0x00                     ;Adress for power up and reset

;*******************SETUP CONSTANTS*******************

INTCON  	EQU	0x0B      ;Interrupt Control Register
ADCON1	EQU	0X9F	
PORTB	EQU	0x06
PORTA   	EQU 	0x05        
TRISA 	EQU 	0x85       
TRISB   	EQU 	0x86      
STATUS 	EQU 	0X03      ;Status register address
COUNT   	EQU 	0x7F      ;This will be our counter variable 
TEMP    	EQU 	0x20      ;Temp file for w register

		ORG		0x00
		goto          main 		  ;Jump over the interrupt address

 
;***************Interrupt Routine***************

 loop:			        ORG     	0x04            ;interrupt address
				
				movwf 	TEMP            ;temp storage for w 
 				incf		COUNT,1       	;Increment COUNT 
 				movlw 	0x0A          ;Move the value 10 into w
 				subwf   	COUNT,0       	;Subtract w from COUNT and result goes to w
 				btfss   	STATUS,0       	;Check the Carry flag. Set if COUNT is equal or greater than W                                        
 				goto    	continue            ;If COUNT is <10, then continue
 				goto    	clear          	;If COUNT is >9, then clear it

continue: 		bcf 	 	INTCON,1		;We need to clear this flag to enable interrupts                                         
          		movfw  	TEMP          	;Restore w to the value before the interrupt
         		retfie                		;Exit the interrupt routine
 
clear: 		clrf		COUNT       	;Set COUNT back to 0
       			bcf	 	INTCON,1   		;We need to clear this flag to enable interrupts                                            
      			retfie  					;Exit interrupt routine
 

;*******************MAIN PROGRAM*********************


 ;****The Interrupt Registers****

				bsf     	INTCON,7    	;GIE – Global interrupt enable (1=enable)
 				bcf		INTCON,1      	;INTF - Clear Flag Bit Just In Case
				bsf    	INTCON,4      	;INTE - RB0 Interrupt Enable (1=enable)


 ;**********Ports*****************

main:  			bcf		STATUS,RP0
				bcf		STATUS,RP1		;SET BANK0
				clrf		PORTA
				clrf		PORTB
				bsf  		STATUS,RP0    	;Switch to Bank 1
				movlw 	b'00000001'        
 				movwf 	TRISB       	        ;Set RB0 as input 	
				movlw	006h
				movwf	ADCON1
 				movlw 	b'000000'                        
				movwf 	TRISA       	        ;Set PortA as output
 				bcf   		STATUS,RP0
				bcf		STATUS,RP1  	; Bank 0
				movf     	COUNT,0     	;Move the contents of Count into W
       			        movwf   	PORTA        	;Now move it to Port A

start:			        btfsc		PORTB,0
				goto		main

				btfss		PORTB,1
				goto     	loop           	;Keep on doing this until an interrupt
		
       	end                      			;End Of Program
 
 
Last edited:
 
hi Raj
Look at this edited version of your program, it works OK in simulation.
My advice would be to use the mnemonics names of the SFR [special function registers] rather than bit numbers.
Are you using MPLAB IDE.?


Code:
    processor 16f877a
    include    <p16f877a.inc> 

    errorlevel  -302  , -207 

    __config _RC_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF &_LVP_OFF

;Set User ID Memory  

;__idlocs        0x1234  


    org    0x00        ;Adress for power up and reset

;*******************SETUP CONSTANTS*******************  

;INTCON    equ    0x0B        ;Interrupt Control Register
;ADCON1    equ    0X9F
;PORTB    equ    0x06
;PORTA    equ    0x05        
;TRISA    equ    0x85       
;TRISB    equ    0x86      
;STATUS    equ    0X03        ;Status register address

COUNT    equ    0x7F        ;This will be our counter variable 
TEMP    equ    0x20        ;Temp file for w register

    org    0x00
    goto    main        ;Jump over the interrupt address

         
;***************Interrupt Routine***************  

isr:    org 0x04        ;interrupt address

    movwf    TEMP        ;temp storage for w 
    incf    COUNT,F        ;Increment COUNT 
    movlw    0x0A        ;Move the value 10 into w
    subwf    COUNT,0        ;Subtract w from COUNT and result goes to w
    btfss    STATUS,0    ;Check the Carry flag. Set if COUNT is equal or greater than W                                        
    goto    continue    ;If COUNT is <10, then continue
    goto    clear        ;If COUNT is >9, then clear it

continue: bcf    INTCON,INTF    ;We need to clear this flag to enable interrupts                                         
    movfw    TEMP        ;Restore w to the value before the interrupt
    retfie            ;Exit the interrupt routine
         
clear:    clrf    COUNT        ;Set COUNT back to 0
    bcf    INTCON,INTF    ;We need to clear this flag to enable interrupts                                            
    retfie            ;Exit interrupt routine
         

;*******************MAIN PROGRAM*********************  

main:
    ;****The Interrupt Registers**** 

    bsf    INTCON,GIE    ;GIE – Global interrupt enable (1=enable)
    bcf    INTCON,INTF    ;INTF - Clear Flag Bit Just In Case
    bsf    INTCON,INTE    ;INTE - RB0 Interrupt Enable (1=enable)
    bsf     INTCON,PEIE

    ;**********Ports***************** 

    bcf    STATUS,RP0
    bcf    STATUS,RP1    ;SET BANK0
    clrf    PORTA
    clrf    PORTB
    bsf    STATUS,RP0    ;Switch to Bank 1
    movlw    b'00000001'        
    movwf    TRISB        ;Set RB0 as input 
    movlw    006h
    movwf    ADCON1
    movlw    b'000000'                        
    movwf    TRISA        ;Set PortA as output
    bcf    STATUS,RP0
    bcf    STATUS,RP1    ; Bank 0
    movf    COUNT,0        ;Move the contents of Count into W
    movwf    PORTA        ;Now move it to Port A


idle_loop:
    nop
    goto    idle_loop        ;Keep on doing this until an interrupt

    end            ;End Of Program
 
1) Count isnt initialized before being put in PORTA at the beginning of code

2) No delay ,this will all happen very fast!

3) If you hold down a button using an interrupt on change, it will increase count once!

4) There is no need for an interrupt either ( I usually don't suggest using them for beginners)

5) If you go to CLear, you don't restore context of W (Doesn't matter for this code, but if you made it longer it would matter)
 
Reactions: 3v0

Hey Eric,

Thanks for the help. I really appreciate it. I got the program working now perfectly. Thanks for the tip on using the mnemonics rather than the bit numbers. For someone like me, it helps a lot. That way I don't have to keep on looking up the different bit numbers!!!! Thanks once again.

Raj H.
 

Hey Birdman,

You helped out again. I really appreciate the tips and pointers. I will probably be getting deeper into Assembly Language my next class, so this stuff really helps. By the way, on that post I made last week, I never did get that program working properly, but appreciate the help you gave me. My professor actually said it was a good program, so that was thanks to your help. Thank you.

Raj H.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…