汇编语言中从 00 到 99 的计数器

发布于 2024-12-19 15:41:17 字数 2845 浏览 1 评论 0原文

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

因为不可能同时显示两个7段,所以我的解决方案是显示十位(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)并坐在那里,它不会退出该循环,也不会重新循环本身。我似乎找不到我的程序逻辑有什么问题

Basically my task is to make the counter on a micro controller board count from 00-99 continuously using assembly language.

because it is not possible to show two 7-Seg to display at the same time, my solution is to display the tens(0), display ones(0), display tens(0), display one(1), display tens(0), display one(2), display tens(0), display one(3), etc. my approach to doing this is to have two loops (one for the tens digit, one for the ones digit) that goes through an array. once the ones digit loop have gone through the entire array, the loop breaks and goes back to the tens digit loop, move the tens digit to the next element, then back to the ones digit loop

    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

right now it seems like the program enters the ones digit loop (LSB) and sits there, it does not exit that loop nor does it reloop itself. I can't seem to find whats wrong in the logic of my program

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦回旧景 2024-12-26 15:41:17

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

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

         '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

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

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

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

Pulling from stack should be done in reverse order from putting on stack.
As Ira pointed out you got your counters mixed up...

You should think of 'displaying two digit number' as a separate thing from increasing some counter in a loop.
Displaying is simple switching 'active' output with a time delay, and setting correct digit value for each display cycle.

         '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

Here is one way of doing this (adjust delay value - 35ms looks to fast...):

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

It would be even better to have display code in a separate routine, and to switch active display more than once per counter increase. That could be a nice exercise for you :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文