Hello, I have a problem with my pic16f877a.
It is working absolutely fine with quartus But whenever i try to build the circuit on the breadboard the rb0 interrupt does not work and i am sure everything is connected right( Vdd, Vss, Oscillators , pin1……)
The code:
MOD EDIT: code tags-JohnInTX
It is working absolutely fine with quartus But whenever i try to build the circuit on the breadboard the rb0 interrupt does not work and i am sure everything is connected right( Vdd, Vss, Oscillators , pin1……)
The code:
Code:
#include "P16F877A.INC"
cblock 0x20
temp
tempp
tempph ;temporary register to store the highest 2 bits of the potentiometer
temppl ;temporary register to store the lowest 8 bits of the potentiometer
tempequal ;counter to check if equal
temph
templp
temphp
templ1 ;temporary register to store the lowest 8 digital bits inside the first LDR
temph1 ;temporary register to store the highest 2 digital bits inside the first LDR
templ2 ;temporary register to store the lowest 8 digital bits inside the second LDR
temph2 ;temporary register to store the highest 2 digital bits inside the second LDR
templ3 ;temporary register to store the lowest 8 digital bits inside the third LDR
temph3 ;temporary register to store the highest 2 digital bits inside the third LDR
templ4 ;temporary register to store the lowest 8 digital bits inside the fourth LDR
temph4 ;temporary register to store the highest 2 digital bits inside the fourth LDR
flag1
flag2
flag3
flag4
counter
onepres ;to direct to the first LDR incase it holds the highest value
twopres ;to direct to the second LDR incase it holds the highest value
threepres ;to direct to the third LDR incase it holds the highest value
fourpres ;to direct to the fourth LDR incase it holds the highest value
TMRCNT
search_hold_counter ;to determine the mode of operation based on the value inside this register. 0x00 Hold 0xFF Search
delay_counter
timer125
track1
counterequalreg ;counter to detect if equal value is present upon comparisin. Incase there is a highest value this counter turns zero
counterhighestreg
cnt1
cnt2
cnt3
cnt4
endc
ORG 0X000
GOTO main
ORG 0X004
GOTO isr
;*
initial
BANKSEL TRISD
CLRF TRISD ;PORTD & PORTB( bit 1-7) as outputs , PORTB(bit 0) as input
MOVLW b'00000001'
MOVWF TRISB
MOVLW b'00000111'
MOVWF TRISE
MOVLW b'00101110'
MOVWF TRISA
BANKSEL INTCON
BSF INTCON, GIE ;Enable global Interrupts
BSF INTCON, INTE;rb0 interrupt
BCF INTCON, INTF;internal flag clear
MOVLW 0XD3
BANKSEL OPTION_REG ;PSA assigned to TMR0, Prescalar = 16, TMR0 clock source
;is the internal
MOVWF OPTION_REG ;instruction cycle clock, External interrupt is on the
;rising egde
BANKSEL search_hold_counter
CLRF search_hold_counter ;clear the counter that test for search/hold, this counter would be filled with 0xFF and would be complemented each time the button is pressed
return
;**
isr
BCF INTCON, T0IE ;This was causing a problem when pressing the button so we added it here
BTFSC INTCON, INTF ;External interrupt has highest priority - tests where the interrupt is coming from
goto search_hold ;if the interrupt is from the button, goto search_hold, if not, just return
RETFIE
;*
main
CALL initial
mainloop
goto hold
start
MOVLW 88H ;10001000
MOVWF ADCON1 ;define all pins analog and vref- & vref+ (see adcon1 reg)
Banksel PORTA ;BANK 0
CALL adc
retest
CALL compareWithP ;are all above p?
bcf STATUS,Z ;clear status
movf counter,1 ;test the counter result from compareWithP, update status
btfsc STATUS,Z ;test value in the counter
CALL loading ;if counter is zero, then all values are below threshold, so go to loading screen
CALL comparehighest ;compares the highest value between LDR's and fills a counter that we can test later to see if there are equal values above threshold
btfsc counterequalreg,0;this is the counter that we test to see if there are any equal values above threshold
goto outequal ;if the counter bit zero is set, it means that more than one value is equal and above threshold -> display '8'
goto masterdisplay ;if there are no equal values above threshold, go to the master display subroutine to display highest value
CALL delay
GOTO start ;Do it again
;**
search_hold ;this is the search/hold code. we come here only when an external interrupt happens. Every time we complement a counter so one time we hold the other we start, one time we hold the other we start, etc.
BCF INTCON, INTF ;Clear the rb0 flag
BSF INTCON, GIE ;set the global interrtupt enable
CLRF PORTB ;turn off any soungs
CLRF PORTD ;turn off display
COMF search_hold_counter,1 ; Toggle the state of the search/hold
btfsc search_hold_counter,1
goto start
goto hold
Return
;*
hold ;this is the hold code, it will stay in this infinite loop until an interrupt happens
movlw b'11110110' ;Infinte loop until the push butoon is pressed
movwf PORTD ;put the letter H in portd
rep
nop
goto rep
;**
comparehighest ;in this code, we test for the highest value between all four LDR's, we also fill a counter if we have two equal values AND above the threshold so we can test it later when we return from the subroutine
movlw 0x00
movwf counterequalreg
movwf tempp ;this is a temporary value
movwf tempph ;this is a temporary high value
movwf temppl ;this is a temporary low value
;we use the tempph and temppl values to save the low and high values of the higheset LDR so we can test them later when we want to display them
compare12H ;we are comparing the high values of LDR1 & LDR2
bcf STATUS,C ;in case there is a previous value in status
movf temph1,0
subwf temph2,0 ;H2-H1
btfsc STATUS,Z ;test Z
goto comp12L ;if zero, go test low bits
btfss STATUS,C ;if its not zero, compare carry
goto takeone ;if there is carry, take LDR1
goto taketwo ;if there is no carry, take LDR2
comp12L ;if the high values are equal, we come here to compare the low values of LDR 1 & 2
bcf STATUS,C ;again, in case
movf templ1,0
subwf templ2,0 ;L2-L1
btfsc STATUS,Z ;test if zero
goto equalcounter12
btfss STATUS,C ;if not zero, test carry
goto takeone ;if there is carry, take LDR1
goto taketwo ;if there is no carry, take LDR2
equalcounter12 ;tests if counter 1&2 are equal
movlw 0xFF
movwf counterequalreg
goto taketwoequal
takeone ;takes one if it is higher
movf temph1,0
movwf tempph ;save H1 on tempH
movf templ1,0
movwf temppl ;save L1 on tempL
incf counterhighestreg
goto comparePrev3H
taketwo ;takes two if it is higher
movf temph2,0
movwf tempph ;save H2 on tempH
movf templ2,0
movwf temppl ;save L2 on tempL
incf counterhighestreg
goto comparePrev3H
taketwoequal ;if both values are equal, we can save any, it won't matter
movf temph2,0
movwf tempph ;save H2 on tempH
movf templ2,0
movwf temppl ;save L2 on tempL
goto comparePrev3H
comparePrev3H ;compare the highest value between the last comparision, with LDR 3, and repeat the same process
bcf STATUS,C
movf tempph,0
subwf temph3,0
btfsc STATUS,Z
goto compPrev3L
btfsc STATUS,C
goto takethree
goto takeold
compPrev3L
bcf STATUS,C
movf temppl,0
subwf templ3,0
btfsc STATUS,Z
goto equalcounter13
btfsc STATUS,C
goto takethree
goto takeold
equalcounter13
movlw 0xFF
movwf counterequalreg
goto takeold
takethree
movf temph3,0
movwf tempph
movf templ3,0
movwf temppl
clrf counterequalreg
incf counterhighestreg
goto comparePrev4H
takeold;if the prevous values are larger, don't take LDR3, do nothing
;no need to do anything, old value already in tempph,temppl
comparePrev4H ;compare the highest value till now with LDR4, adn repeat the same processs
bcf STATUS,C
movf tempph,0
subwf temph4,0
btfsc STATUS,Z
goto compPrev4L
btfsc STATUS,C
goto takefour
goto takenewold
compPrev4L
bcf STATUS,C
movf temppl,0
subwf templ4,0
btfsc STATUS,Z
goto equalcounter14
btfsc STATUS,C
goto takefour
goto takenewold
equalcounter14
movlw 0xFF
movwf counterequalreg
goto takenewold
takefour
movf temph4,0
movwf tempph
movf templ4,0
movwf temppl
clrf counterequalreg
incf counterhighestreg
goto comparisondone
takenewold
;also no need to do anything
comparisondone
return
;*
loading ;this is the loading code, how it works is the following, after each dash, we add a delay of a randome time we chose on the delay_long subroutine, then we test again by doing the conversion and testing if the LDR's are higher than the threshold. If not, we stay inside the loading code, if one became higher, we go and test to see which one is higher
banksel TRISD
clrf TRISD ;make portd outpout
banksel PORTD
search
movlw B'00000001' ;choose first 7seg dash
movwf PORTD ;display on portD
CALL delay_long ;longer delay
call retest_adc ;retest, we are using another subrouting (not the same one as in the main subroutine), since we need this to be independent. Using the one in the main will keep restarting the loading screen and we would only see the first loading dash, since every time it's repeating the testing and going to the loading subrouting and displaying only the first dahs
bcf STATUS,Z ;in case clear status
movf counter,1 ;test counter again
btfss STATUS,Z ;skip if all are below zero
goto endloading ;if counter is not zero, exit loading
movlw B'00000010'
movwf PORTD
CALL delay_long
call retest_adc
bcf STATUS,Z
movf counter,1
btfss STATUS,Z
goto endloading
movlw B'00000100'
movwf PORTD
CALL delay_long
call retest_adc
bcf STATUS,Z
movf counter,1
btfss STATUS,Z
goto endloading
movlw B'00001000'
movwf PORTD
CALL delay_long
call retest_adc
bcf STATUS,Z
movf counter,1
btfss STATUS,Z
goto endloading
movlw B'00010000'
movwf PORTD
CALL delay_long
call retest_adc
bcf STATUS,Z
movf counter,1
btfss STATUS,Z
goto endloading
movlw B'00100000'
movwf PORTD
CALL delay_long
call retest_adc
bcf STATUS,Z
movf counter,1
btfss STATUS,Z
goto endloading
goto search
endloading
return
;**
retest_adc ; this is used to continuously test the input values for the loading subroutine
MOVLW 88H
MOVWF ADCON1
Banksel PORTA ;BANK 0
CALL adc
CALL compareWithP
return
;*
compareWithP ;here we compare all values with the threshold to see if all are lower, we do this by defining a counter and putting in it the value 4. every time we find a value that is lower than the threshold, we decrease the counter. If all values are lower than the threshold, the counter will have a zero inside it. We can test this when we go out of the subroutine
movlw .4
movwf counter ;this is the counter mentioned earlier
;we test each value with by by comparing the high values, if they are equal, we move to comparing the low values.
compare1p
movf temphp,0
subwf temph1,0 ;H1-Hp
btfsc STATUS,Z ;test if zero
goto compl1 ;if zero, goto compare low 1
btfsc STATUS,C ;test carry
goto final1 ;if there is carry, then P is larger than 1, so
decf counter,1 ;decrease the counter
goto final1
compl1
movf templp,0 ;low potentiometer
subwf templ1,0 ;L1-LP
btfsc STATUS,C ;test carry
goto final1 ;if no carry
decf counter,1 ;if carry, decrease the counter
final1
movwf onepres; save value in onePres, this is not used, just a temporary value
;repeat
compare2p
movf temphp,0
subwf temph2,0
btfsc STATUS,Z
goto compl2
btfsc STATUS,C
goto final2
decf counter,1
goto final2
compl2
movf templp,0
subwf templ2,0
btfsc STATUS,C
goto final2
decf counter,1
final2
movwf twopres ;just a temporary value
;repeat
compare3p
movf temphp,0
subwf temph3,0
btfsc STATUS,Z
goto compl3
btfsc STATUS,C
goto final3
decf counter,1
goto final3
compl3
movf templp,0
subwf templ3,0
btfsc STATUS,C
goto final3
decf counter,1
final3
movwf threepres ;just a temporary value
;repeat
compare4p
movf temphp,0
subwf temph4,0
btfsc STATUS,Z
goto compl4
btfsc STATUS,C
goto final4
decf counter,1
goto final4
compl4
movf templp,0
subwf templ4,0
btfsc STATUS,C
goto final4
decf counter,1
final4
movwf fourpres ;just a temporary value
return
;**
adc
adcp
MOVLW 09H ;00001001 choose AN1 input (see adcon0 reg)
MOVWF ADCON0 ;move values to adcon0
CALL delay
BSF ADCON0,GO ;start conversion
waitp
BTFSS PIR1,ADIF ;keep testing the ADIF flag until the conversion is complete
GOTO waitp
bcf PIR1, ADIF ;clear ADIF when conversion is done
Banksel TRISA
MOVF ADRESL,W
Banksel PORTA
MOVWF templp ;save adresl to temp register
MOVF ADRESH,W
MOVWF temphp ;save adresh to temp register
adc1 ;choose an4
MOVLW 21H
MOVWF ADCON0
CALL delay
BSF ADCON0,GO
wait1
BTFSS PIR1,ADIF
GOTO wait1
bcf PIR1, ADIF
Banksel TRISA
MOVF ADRESL,W
Banksel PORTA
MOVWF templ1
MOVF ADRESH,W
MOVWF temph1
adc2 ;choose an5
MOVLW 29H
MOVWF ADCON0
CALL delay
BSF ADCON0,GO
wait2
BTFSS PIR1,ADIF
GOTO wait2
bcf PIR1, ADIF
Banksel TRISA
MOVF ADRESL,W
Banksel PORTA
MOVWF templ2
MOVF ADRESH,W
MOVWF temph2
adc3 ;choose an6
MOVLW 31H
MOVWF ADCON0
CALL delay
BSF ADCON0,GO
wait3
BTFSS PIR1,ADIF
GOTO wait3
bcf PIR1, ADIF
Banksel TRISA
MOVF ADRESL,W
Banksel PORTA
MOVWF templ3
MOVF ADRESH,W
MOVWF temph3
adc4 ;choose an7
MOVLW 39H
MOVWF ADCON0
CALL delay
BSF ADCON0,GO
wait4
BTFSS PIR1,ADIF
GOTO wait4
bcf PIR1, ADIF
Banksel TRISA
MOVF ADRESL,W
Banksel PORTA
MOVWF templ4
MOVF ADRESH,W
MOVWF temph4
return
;**
masterdisplay
movlw .30
movwf timer125
clrf cnt1 ;to use as a counter
movf tempph,0; move highest high to working register to copamre
subwf temph1,0;subtract the highest high from ADRESH of LDR1 to check if equal
btfsc STATUS,Z;to check if the ADRESH of LDR1 equals to the highest measered high of LDR1
incf cnt1; increase counter
movf temppl,0; move highest low on working register to compare
subwf templ1,0
btfsc STATUS,Z;to check if the ADRESL of LDR1 equals to the highest measered low
incf cnt1; increase counter
btfsc cnt1,1; afetr increasing on high and low we are know sure that LDR1 is the highest measured
goto out1;
clrf cnt2; same as above
movf tempph,0
subwf temph2,0
btfsc STATUS,Z
incf cnt2
movf temppl,0
subwf templ2,0
btfsc STATUS,Z
incf cnt2
btfsc cnt2,1
goto out2
clrf cnt3; same as above
movf tempph,0
subwf temph3,0
btfsc STATUS,Z
incf cnt3
movf temppl,0
subwf templ3,0
btfsc STATUS,Z
incf cnt3
btfsc cnt3,1
goto out3
clrf cnt4; same as above
movf tempph,0
subwf temph4,0
btfsc STATUS,Z
incf cnt4
movf temppl,0
subwf templ4,0
btfsc STATUS,Z
incf cnt4
btfsc cnt4,1
goto out4
goto start
outequal
MOVLW B'11111111'
MOVWF PORTD
clrf track1 ;this is to clear the counter that tests if we are on one of the values so we don't get a sound twice in a row for one value
GOTO start
out1
speaker1
bcf track1,3
bcf track1,4
bcf track1,2
MOVLW B'10000110'
MOVWF PORTD
btfsc track1,1;this is a counter we use so we don't output the sound twice in a row if the highest value didn't change
goto start
MOVLW .81 ;each delay is 154.4micro seconds long, in the out1 code, we use it twice every time, so we multiply it by 81 to get around 0.5 seconds
MOVWF delay_counter
start1
BSF PORTB,RB1 ;to generate a square periodic wave with deferent frequencies
bsf track1,1
Call delay ;here we use the delay twice to generate a square wave. we do the same with out 2,3,4 but we use the delay more times to get other sounds
BCF PORTB,RB1
Call delay
decfsz delay_counter
GOTO start1
goto start
out2
speaker2
bcf track1,1
bcf track1,3
bcf track1,4
MOVLW B'11011011'
MOVWF PORTD
btfsc track1,2
goto start
MOVLW .40 ;each delay is 154.4micro seconds long, in the out2 code, we use it four times every time, so we multiply it by 40 to get around 0.5 seconds
MOVWF delay_counter
start2
BSF PORTB,RB1
bsf track1,2
Call delay
Call delay
BCF PORTB,RB1
Call delay
Call delay
decfsz delay_counter
GOTO start2
goto start
out3
speaker3
bcf track1,1
bcf track1,4
bcf track1,2
MOVLW B'11001111'
MOVWF PORTD
btfsc track1,3
goto start
MOVLW .27 ;each delay is 154.4micro seconds long, in the out3 code, we use it six times every time, so we multiply it by 27 to get around 0.5 seconds
MOVWF delay_counter
start3
BSF PORTB,RB1
bsf track1,3
Call delay
Call delay
Call delay
BCF PORTB,RB1
Call delay
Call delay
Call delay
decfsz delay_counter
GOTO start3
goto start
out4
speaker4
bcf track1,1
bcf track1,3
bcf track1,2
MOVLW B'11100110'
MOVWF PORTD
btfsc track1,4
goto start
MOVLW .20 ;each delay is 154.4micro seconds long, in the out4 code, we use it eight times every time, so we multiply it by 20 to get around 0.5 seconds
MOVWF delay_counter
start4
BSF PORTB,RB1
bsf track1,4
Call delay
Call delay
Call delay
Call delay
BCF PORTB,RB1
Call delay
Call delay
Call delay
Call delay
decfsz delay_counter
GOTO start4
goto start
return
;**
delay
MOVLW 0xFF
MOVWF temp
L1 DECFSZ temp,1
GOTO L1
RETURN
delay_long
MOVLW 0X2F ;specify counter value (times we want to repeat the normal delay), this is an assumption that the delay is repeated 2F times
MOVWF delay_counter
repeat_delay
Call delay ;keep calling normal delay until counter is zero
decfsz delay_counter
goto repeat_delay
return
;*
end
Last edited by a moderator: