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',

Другие вопросы по тегам