Счетчик от 00 до 99 на ассемблере - PullRequest
1 голос
/ 05 декабря 2011

В основном моя задача состоит в том, чтобы счетчик на плате микроконтроллера непрерывно отсчитывал от 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) и находится там, она не выходит из этого цикла и не перезапускает себя.Кажется, я не могу найти, что не так в логике моей программы

1 Ответ

3 голосов
/ 08 января 2012

Вытаскивание из стека должно производиться в порядке, обратном укладке в стек. Как указала Ира, вы перепутали счетчики ...

Вы должны думать о «отображении двузначного числа» как об отдельной вещи от увеличения некоторого счетчика в цикле. Отображение - это простое переключение «активного» выхода с задержкой по времени и установка правильного цифрового значения для каждого цикла отображения.

         '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

Было бы еще лучше иметь код дисплея в отдельной подпрограмме и переключать активный дисплей более одного раза на увеличение счетчика. Это может быть хорошим упражнением для вас:)

...