TMR0 на языке ассемблера для рис 16f84A
Я пытаюсь использовать TMR0 в своем коде, чтобы заставить зуммер работать над ошибкой, но мне трудно его использовать, я уже потратил 4 часа, пытаясь разобраться с этим, так что теперь я здесь прошу помогите, было бы желательно, ошибка работает на 4Mhz и зуммер BIT 0 на PORTB, в идеале я хочу, чтобы он включался и выключался при движении задним ходом, но в этот момент я просто согласился бы заставить его гудеть один раз
это код, так как известно, что при нажатии кнопки багги движется вперед, ненадолго переворачивается, затем поворачивается на 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
1 ответ
В вашей программе прерываний есть несколько проблем. Во-первых, вы не очищаете флаг прерывания 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'
,