assembly pic组件上下计数器只能增加到1

mbjcgjjk  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(159)

尝试在0和15之间创建一个计数器,但目前它只能从0增加到1,然后再回到0。到目前为止,我的代码如下:

LIST    P=16f84A, R=HEX   
    __FUSES _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_ON
    include <P16F84A.inc>    ;include the file mentioned

ctrhi   EQU     0x0020     
ctrmi   EQU     0x0021
ctrlo   EQU     0x0022

    ;start of program
    bsf STATUS, RP0      
    movlw B'11111110'    
    movwf TRISA          
    clrf TRISB          
    bcf STATUS, RP0      
    movlw   D'255'      
    movwf   ctrlo       
    movlw   D'127'
    movwf   ctrmi       
    clrf    PORTB

loop:                   
    btfsc   PORTA, 1    
    goto    loop1       
    btfsc   PORTA, 2     
    goto    loop2      

    goto    loop

loop1:
    btfsc   PORTA, 1     
    goto    loop1      
waitforrelease:
    call    delay      
    btfsc   PORTA,1     
    goto    waitforrelease
    movf    PORTB, W    
    addlw   1           
    andlw   0x0F       
    movwf   PORTB      
    goto    loop      

loop2:
    btfsc PORTA, 2 
    goto loop2 
waitforrelease2:
    call delay 
    btfsc PORTA, 2
    goto waitforrelease2
    movf PORTB, W 
    sublw 1
    andlw 0x0F
    movwf PORTB
    goto loop

delay:                  
    movlw   D'10'       
    movwf   ctrhi
    movlw   D'255'
    movwf   ctrmi
delay_loop:
    decfsz  ctrmi, F
    goto    delay_loop
    decfsz  ctrhi, F
    goto    delay_loop
    return

    END

有什么建议,我可以使这个增加,并减少回0与按钮RA1和RA2?
谢谢

wqlqzqxt

wqlqzqxt1#

好吧,因为我喜欢玩PICSIMlab,我把它下载到我的电脑上,用你的代码玩。但是我想先修复你的代码,无论是美学上还是逻辑上,以提高可读性,使其按预期工作。
当我在PICSIMlab中尝试代码时,我注意到按钮连接为负逻辑输入。也就是说,当它们未被按下时,RAx引脚上有+VDD(逻辑1),当它们被按下时,RAx引脚上将有GND(逻辑0)。因此,我相应地将btfss指令固定为btfsc
我不知道你是否熟悉C语言,但我想发布以下伪C代码,在我们看到固定的汇编代码之前,它具有与汇编代码相同的功能。这可能有助于弄清楚我们想要在汇编代码中做什么,因为汇编有点难以阅读。我没有实现delay()函数,因为它可能是构建的-在C编程环境中或特定于C编程环境。

void countUpPressed() {
    PORTB = ++PORTB & 0xF;
}

void countDownPressed() {
    if(PORTB == 0) PORTB = 15;
    else PORTB--;
}

void main(void) {
    
    while(1) { // main:
        if(PORTA & 1 == 0) { // is count up button pressed?
            delay(); // Yes, but filter out the noise first
            if(PORTA & 1 == 0) { // Is the button press still stable
                countUpPressed(); // Yes, then proceed
            }
            while(PORTA & 1 == 0)
                ; // Wait for it to be released
        }
        else if(PORTA & 2 == 0) { // is count up button pressed?
            delay(); // Yes, but filter out the noise first
            if(PORTA & 2 == 0) { // Is the button press still stable
                countDownPressed(); // Yes, then proceed
            }
            while(PORTA & 2 == 0)
                ; // Wait for it to be released
        }
        // Loop forever
    }
    
}

现在来发布修复和改进的汇编代码。我放了一些注解来解释特定行的作用,以便给予你一些关于PIC汇编编程的新视角。
顺便说一句,我使用gputils gpasm编译器v1.5.2编译了汇编代码。

LIST    P=16f84A, R=HEX
    __FUSES _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_ON
    include <P16F84A.inc>    ;include the file mentioned

; 0xC is where the GPR regions start
ctrhi   EQU 0xC
ctrmi   EQU 0xD
ctrlo   EQU 0xE

    ; Start from restart vector
    ORG 0

    ;start of program
    bsf     STATUS, RP0
    movlw   B'11111110'
    movwf   TRISA
    clrf    TRISB
    bcf     STATUS, RP0
    movlw   D'255'
    movwf   ctrlo
    movlw   D'127'
    movwf   ctrmi
    clrf    PORTB

main:
    btfsc   PORTA, 1
    goto    checkCountDown ; No count up input, check for count down input
    call    delay
    btfsc   PORTA, 1 ; Confirm the press
    goto    checkCountDown ; False trigger, check count down input
    call    countUpPressed ; Press confirmed, handle count up
    ; Wait for release right AFTER HANDLING THE EVENT
    btfss   PORTA, 1
    goto    $-1 ; This is another way to loop. It means goto PC-1 until the
                ; button is released. It is a good way if you don't wanna use
                ; a label for it
checkCountDown:
    btfsc   PORTA, 2
    goto    main ; No input keep checking
    call    delay
    btfsc   PORTA, 2 ; Confirm the press
    goto    main ; False trigger, keep checking
    call    countDownPressed ; Press confirmed, handle count down
    ; Wait for release right AFTER HANDLING THE EVENT
    btfss   PORTA, 2
    goto    $-1

    goto    main

; Count up press handler subroutine
countUpPressed:
    incf    PORTB, W ; Increment the value on PORTB and save it to W
    andlw   0xF ; Mask the upper bits so that it doesn't exceed 15 decimal
    movwf   PORTB ; Move the resulted value to the PORTB
    return

; Count down press handler subroutine
countDownPressed:
    movf    PORTB, F ; This instruction is good for checking whether the value
                     ; in a register is zero or not. If it is zero, the Z(ero)
                     ; flag of the STATUS register will set by the CPU automatically
    btfss   STATUS, Z ; Check if zero, and handle the zero apart
    goto    countDownDoCountDown
    ; If we reach here is because the value is zero and we will roll the value up
    ; to 15 decimal to keep counting down within the 15 - 0 bounds
    movlw   0xF
    movwf   PORTB
    ; We've updated the current value, nothing more to do here.
    return
countDownDoCountDown:
    ; If we reach here is because the value is greater than zero and we will
    ; keep decrementing 1 by 1, and then output the value
    decf    PORTB, F
    return

; Xms delay routine
delay:
    movlw   D'10'
    movwf   ctrhi
    movlw   D'255'
    movwf   ctrmi
delay_loop:
    decfsz  ctrmi, F
    goto    delay_loop
    decfsz  ctrhi, F
    goto    delay_loop
    return

    END

现在,您应该在连接到PORTB的LED上看到二进制输出,范围为0到15,用于递增,范围为15到0,用于递减。

相关问题