用于pic 16f84A的汇编语言的TMR0

时间:2016-02-05 00:40:26

标签: assembly microcontroller pic

我正试图在我的代码中使用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

1 个答案:

答案 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'