0
votes

i'm trying to utilize TMR0 in my code to get a buzzer working on a buggy to but i'm having a hard time utilizing it, ive already spent 4 hours trying to get my head around it so now i'm here asking for help, it would be appreciated, the buggy is running at 4Mhz and the buzzer is BIT 0 on PORTB, ideally i want it to buzz on and off while reversing but at this point i'd just settle at getting it to buzz once

this is the code, as of know the buggy goes forward on a button press it will reverse for a short time then proceed to turn 90 degree then goes forward again and repeats this.

; Buggy.ASM 11MAR02

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
; Configuration data 
; PICmicro MCU type: 16F84
; Oscillator:  XTAL mode, fast, VR1 fully clockwise (max.rate)
; LCD display: off 
; 7-segment display: off
; Version 2 board settings: J14 links: Digital 
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 
;
; The following line embeds configuration data into the PICmicro
    LIST P=16F84
    __CONFIG H'3FFA'                ; XTAL mode

;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 

; using aliases, bit names and conditional loops

#DEFINE PAGE0   BCF STATUS,5
#DEFINE PAGE1   BSF STATUS,5

STATUS  EQU H'03'       ; STATUS register
TRISB   EQU H'86'       ; Port B direction register
PORTB   EQU H'06'       ; Port B data register
TRISA   EQU H'85'       ; Port A direction register
PORTA   EQU H'05'       ; Port A data register
OPSHUN  EQU H'81'       ;OPTION_REGISTER
INTCON  EQU H'0B'       ;INTCON REGISTER
TMR0    EQU H'01'       ;
TMRCNT  EQU H'20'       ;TMR COUNT

d1  EQU H'22'       ;
d2  EQU H'23'       ;
d3  EQU H'24'       ;

ORG 0       ; Reset vector
GOTO    5       ; Goto start of program
ORG 4       ; Interrupt vector
GOTO    BUZZ        ; Goto BUZZ
ORG 5       ; Start of program memory

CLRF    PORTB       ; clear Port B data register
CLRF    PORTA       ;
PAGE1           ; PAGE1
MOVLW   B'11000010' ;
MOVWF   OPSHUN      ;set timer ratio to 1:8 (TMR0 rate)
MOVLW   B'11111111' ;
MOVWF   TRISA       ; Set port A to input
CLRF    TRISB       ; Port B direction register for output
PAGE0
MOVLW   B'10100100' ;
MOVWF   INTCON
CLRF    TMR0
MOVLW   D'15'       ;
MOVWF   TMRCNT      ;


FORWARD MOVLW   D'80' 
MOVWF   PORTB       ; Set Port B to 80
BTFSC   PORTA,0     ;
GOTO    BACK_R      ;BACK RIGHT
BTFSC   PORTA,1     ;
GOTO    BACK_L      ;BACK LEFT
GOTO    FORWARD     ;

BACK_R  
MOVLW   D'164'      ;
MOVWF   PORTB       ;
BCF INTCON,2        ; ENABLE TMR0 INTTERUP
CALL    DELAY_R     ;
MOVLW   D'148'      ;
MOVWF   PORTB       ;
CALL    DELAY_R     ;
GOTO    FORWARD     ;

BACK_L  
MOVLW   D'162'      ;
MOVWF   PORTB       ;
BCF INTCON,2        ; ENABLE TMR0 INTTERUP
CALL    DELAY_R     ;
MOVLW   D'98'       ;
MOVWF   PORTB       ;
CALL    DELAY_R     ;
GOTO    FORWARD     ;


BUZZ
BSF     PORTB,0 
DECFSZ  TMRCNT      ;
GOTO    BUZZ                        
MOVLW   d'15'       ;RESET THE DELAY COUNTER
MOVWF   TMRCNT      ;
BCF     PORTB,0
RETFIE

DELAY_R     

movlw   0xFF
movwf   d1
movlw   0xFF
movwf   d2
movlw   0x05
movwf   d3
goto    Delay_0

DELAY_T     
movlw   0xFF
movwf   d1
movlw   0xFF
movwf   d2
movlw   0x05
movwf   d3

Delay_0
decfsz  d1, f
goto    Delay_0
decfsz  d2, f
goto    Delay_0
decfsz  d3, f
goto    Delay_0
        ;4 cycles

return






END         ; final statement
1

1 Answers

0
votes

There are a few problems in your interrupt routine. One is that you are not clearing the Timer0 interrupt flag (T0IF in INTCON register). You can add this right at the beginning of the BUZZ routine:

BCF     INTCON,2

If you don't do this, the interrupt won't fire next time.

Another issue is in this line:

GOTO    BUZZ

Here you are decrementing TMRCNT very quickly in a loop and then just turning the buzzer off when it gets to zero. This way, you will barely hear the buzzer sound. You should just replace it with a RETFIE.

You also need to turn Timer0 interrupts off after you turn the buzzer off. So you will end up with something like this:

BUZZ
BCF     INTCON,2    ; clear Timer0 interrupt flag
BSF     PORTB,0     ; turn buzzer on
DECFSZ  TMRCNT
RETFIE              ; return to main program, keeping buzzer on until next interrupt
MOVLW   D'15'       ; reset the delay counter
MOVWF   TMRCNT
BCF     PORTB,0     ; turn buzzer off
BCF     INTCON,5    ; disable Timer0 interrupts
RETFIE

Also, in your other functions, whenever you write something to the PORTB register, you must take care not to overwrite bit 0, which will be controlling the buzzer.

You should also replace BCF INTCON,2 by BSF, INTCON,5 in your code, and initialise INTCON with B'10000100'.