我正试图在我的代码中使用TMR0来制作一个关于越野车的蜂鸣器,但我很难利用它,我已经花了4个小时试图让我的头围绕它所以现在我在这里寻求帮助,我们将不胜感激,这款越野车在4Mhz运行,PORTB上的蜂鸣器是BIT 0,理想情况下,我希望它在倒车时能够开启和关闭,但此时我只是满足于让它嗡嗡作响一旦
这是代码,因为知道越野车按下按钮它会在短时间内反转然后继续转90度然后再前进并重复此操作。
; 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
答案 0 :(得分:0)
您的中断例程中存在一些问题。一个是您没有清除Timer0中断标志(T0IF
寄存器中的INTCON
)。您可以在BUZZ
例程的开头添加此权限:
BCF INTCON,2
如果你不这样做,下次不会触发中断。
另一个问题是:
GOTO BUZZ
这里你在一个循环中非常快地递减TMRCNT
,然后在它变为零时关闭蜂鸣器。这样,你几乎听不到蜂鸣器的声音。您应该用RETFIE
替换它。
关闭蜂鸣器后,还需要关闭Timer0中断。所以你最终会得到这样的东西:
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
此外,在您的其他功能中,无论何时向PORTB
寄存器写入内容,都必须注意不要覆盖位0 ,这将控制蜂鸣器。
您还应该在代码中将BCF INTCON,2
替换为BSF, INTCON,5
,并使用INTCON
初始化B'10000100'
。