1

基本上我的任务是使用汇编语言使微控制器板上的计数器从 00-99 连续计数。

因为不可能同时显示两个7-Seg,所以我的解决方法是显示十位(0),显示一个(0),显示十位(0),显示一个(1),显示十位( 0),显示一(2),显示十(0),显示一(3)等。我这样做的方法是有两个循环(一个用于十位,一个用于个位),通过一个大批。一旦个位循环遍历整个数组,循环中断并返回十位循环,将十位移动到下一个元素,然后返回个位循环

    MSB_Display     equ     $0B ; display on 'tens' digit/second most right of 7-Seg
    LSB_Display     equ     $07 ; display on 'ones' digit/most right of 7-Seg


    D_1MS           equ     24000 / 6

    DelayVal        equ     35      ; 35 ms delay simulates both Hex Displays on at once

                    org     $1000
    ;                             Lookup table for LED segments
    array           db      $3F,$06,$5B,$4F,$66,$6D,$7C,$07,$7F,$6F
    ;                        0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9

    ; Memory Reserved for Delay Routine
    DCount          ds      1
    Counter         ds      1
    countones       db      0
    counttens       db      0

            org     $2000           ; Program starts here
            lds     #$2000          ; Initalize the stack

    ; Configure Hardware
            ldaa    #$FF
            staa    DDRB            ; Make PORTB output
            staa    DDRP            ; PTP as Output

    start
            clr     countones       ; clear count back to 0
            clr     counttens
        ldx     #array


    MSB
            ldaa    1,x+
            staa    PORTB
            ldaa    #MSB_Display
            staa    PTP             ; turn off 7-segment display
            bsr     Delay_ms
            inc     counttens
            ldaa    counttens
            cmpa    #10
            bne     LSB


    LSB
            ldy     #array
        ldab    1,y+
            stab    PORTB
            ldab    #LSB_Display
            stab    PTP
            bsr     Delay_ms
            inc     countones
            ldaa    countones
            cmpa    #10
            bne     LSB


            bra     MSB


            Delay_ms
                    psha              
                    pshy
                    ldaa   #DelayVal        ; Number of msec to delay
                    staa    DCount          ; store delay counter
                    ldaa    DCount          ; delay Dcount ms
                    staa    Counter
            Delay1  ldy     #D_1MS          ; 6000 x 4 = 24,000 cycles = 1ms
            Delay2  dey                     ; this instruction takes 1 cycle
                    bne     Delay2          ; this instruction takes 3 cycles
                    dec     Counter
                    bne     Delay1          ; not Dcount ms yet, delay again
                    pula                    ; Restore contents of ACC A before returning
                    puly
                    rts
                    end

现在似乎程序进入了个位循环(LSB)并坐在那里,它没有退出该循环,也不会重新循环自身。我似乎无法在我的程序逻辑中找到什么问题

4

1 回答 1

3

从堆栈中拉出应该按照与放入堆栈相反的顺序进行。正如艾拉指出的那样,您的计数器混淆了...

您应该将“显示两位数”视为与在循环中增加一些计数器不同的事情。显示是带有时间延迟的简单切换“活动”输出,并为每个显示周期设置正确的数字值。

         'tens' = 0
loop10   'ones' = 0
loop1    display 'tens'
         delay
         display 'ones'
         delay
         inc 'ones'
         goto loop1 if 'ones' less than 10
         inc 'tens'
         goto loop10 if 'tens' less than 10

这是执行此操作的一种方法(调整延迟值 - 35ms 看起来很快......):

MSB_Display     equ     $0B ; display on 'tens' digit/second most right of 7-Seg
LSB_Display     equ     $07 ; display on 'ones' digit/most right of 7-Seg


D_1MS           equ     24000 / 6

DelayVal        equ     35      ; 35 ms delay simulates both Hex Displays on at once

                org     $1000
;                             Lookup table for LED segments
array           db      $3F,$06,$5B,$4F,$66,$6D,$7C,$07,$7F,$6F
;                        0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9

; Memory Reserved for Delay Routine
DCount          ds      1
Counter         ds      1
countones       db      0
counttens       db      0

        org     $2000           ; Program starts here
        lds     #$2000          ; Initalize the stack

; Configure Hardware
        ldaa    #$FF
        staa    DDRB            ; Make PORTB output
        staa    DDRP            ; PTP as Output

start
        clr     counttens       ; 'tens' = 0
        ldx     #array          ; x will point to 'tens'

MSB     clr     countones       ; 'ones' = 0
        ldy     #array          ; y will point to 'ones'
                                ; at every start of 'tens' cycle
LSB
        ldaa    x               ; Set value of 'tens' display
                                ; Do not use 1,x+ here
                                ; You don't want to increment 'tens'
                                ; every time you display 'ones'
        staa    PORTB
        ldaa    #MSB_Display
        staa    PTP             ; turn on 'tens' 7-segment display
        bsr     Delay_ms        ; let it be lit for a while

        ldab    1,y+            ; set value of 'ones' display (and increment it)
        stab    PORTB
        ldab    #LSB_Display
        stab    PTP             ; turn on 'ones' 7-segment display
        bsr     Delay_ms        ; let it be lit for a while

        inc     countones
        ldaa    countones
        cmpa    #10
        bne     LSB

        inx                     ; now increment 'tens'
        inc     counttens
        ldaa    counttens
        cmpa    #10
        bne     MSB

        bra     start           ; start from '00'

Delay_ms
        psha              
        pshy
        ldaa   #DelayVal        ; Number of msec to delay
        staa    Counter
Delay1  ldy     #D_1MS          ; 6000 x 4 = 24,000 cycles = 1ms
Delay2  dey                     ; this instruction takes 1 cycle
        bne     Delay2          ; this instruction takes 3 cycles
        dec     Counter
        bne     Delay1          ; not Dcount ms yet, delay again
        puly                    ; Restore contents of ACC A before returning
        pula
        rts
        end

将显示代码放在单独的例程中会更好,并且每次计数器增加一次以上切换活动显示。这对你来说可能是一个很好的练习:)

于 2012-01-08T13:43:35.173 回答