中断 IQR 和 XIRQ - 汇编

Interrupts IQR and XIRQ - assembly

我一直在为与 IRQ(中断本身)相关的话题苦苦挣扎;我用的是旧的 MC68HC11

练习了一段时间;我决定继续检查本章中显示的最难的练习,这就是为什么我找到了一个有趣的练习(而且有点棘手)

看看这个:

这是我目前尝试的方法(这只是一个大纲):

Do NOTE:

FLAGNMI means XIRQ

FLAGIQR means IRQ

IRQ                 EQU     $FFF2
XIRQ                EQU     $FFF4
RESET               EQU     $FFFE
RWM                 EQU     [=10=]00
ROM                 EQU     $C000
LEDS                EQU     04
VARIABLE            EQU     03
MECHANICAL_SEAL     EQU     [=10=]80
CONFIG              EQU     39


                    CLR     VALUE
                    CLR     BALANCE
                    CLR     PRICE_SODA
                    TPA
                    ANDA    #(MASKNMI&MASKIRQ)
                    TAP
                    LDAA    CONFIG
                    ORAA    #MASKEDGE
                    STAA    CONFIG
                    CLR     FLAGIRQ
                    CLR     FLAGNMI
                    LDAA    #[=10=]
                    STAA    REMAINING_MONEY
                    LDAA    #$FF
                    STAA    LEDS
                    
                    
Main                
                    LDAA    FLAGNMI
                    BNE     COINS   
                    CLR     FLAGNMI
                    LDAA    FLAGIRQ
                    BEQ     Main
                    CLR     FLAGIRQ 
                    JSR     DRINKS
                    BRA     Main

我卡在这里了;我可以想象一些使用 C 来解决它的方法,但这对我没有太大帮助(不是在汇编中)。

可以帮我吗?

编辑:

;*******************************************************************************
; MCU specific
;*******************************************************************************

REGS                equ       00               ;register base
PORTB               equ       REGS+            ;port B (output only)
PORTC               equ       REGS+            ;port C
OPTION              equ       REGS+            ;System Configuration Options
STACKTOP            equ       FF               ;Top of Stack
RAM                 equ       [=11=]40               ;beginning of RAM
ROM                 equ       $F800               ;beginning of ROM

Virq                equ       $FFF2               ;IRQ vector
Vxirq               equ       $FFF4               ;XIRQ vector
Vreset              equ       $FFFE               ;reset vector

X.                  equ       %01000000           ;XIRQ disable
IRQE.               equ       %00100000           ;IRQ Edge sensitive

;*******************************************************************************
; Application specific
;*******************************************************************************

LED                 equ       PORTB               ;bitmap of LED
COIN                equ       PORTC               ;coin value is here
SODA_CHOICE         equ       PORTC               ;drink choice as bitmap
SODA_PULSES         equ       [=11=]80               ;bitmap of soda pulses

INITIAL_DRINKS      equ       4                   ;number of initial drinks
DRINK_COST          equ       20                  ;drink cost in dollars

NOT                 equ       $FF                 ;XOR value to invert bits
;*******************************************************************************
                    org       RAM
;*******************************************************************************

soda_counters       rmb       8                   ;array of soda counters
money_total         rmb       2                   ;keeps money in machine

;*******************************************************************************
                    org       ROM
;*******************************************************************************

Start               
                    lds       #STACKTOP
                    bsr       InitMachine

                    tpa
                    anda      #X.^NOT             ;enable XIRQ interrupts
                    tap

                    ldaa       OPTION
                    oraa       #IRQE.              ;make IRQ edge sensitive
                    staa       OPTION

Loop_a              cli                           ;enable interrupts
                    wai                           ;low power mode until interrupt
                    bra       Loop_a              ;endless loop (all work is done in interrupt handlers)

;*******************************************************************************

InitMachine         
          ;-------------------------------------- ;assume INITIAL_DRINKS of each type
                    ldx       #soda_counters      ;X -> drink counters
                    ldaa      #INITIAL_DRINKS     ;A = number of drinks initially
Loop_1              staa      ,x                  ;update current counter
                    inx                           ;X -> next drink counter
                    cpx       #soda_counters+8
                    blo       Loop_1              ;repeat for all drink counters
                    bsr       AdjustLeds          ;adjust LED indicators
          ;--------------------------------------
                    clra
                    clrb
                    std       money_total         ;zero initial money balance
                    rts

;*******************************************************************************

AdjustLeds          
                    ldx       #soda_counters      ;X -> soda counters
                    clra                          ;bit mask of soda LED
Loop_2             tst       ,x                  ;test current soda counter
                    clc                           ;assume a zero
                    beq       Cont_1              ;if zero, go put a zero in the mask
                    sec                           ;else we'll put a one in the mask
Cont_1             rora                          ;shift in zero/one bit for this LED
                    inx                           ;X -> next soda counter
                    cpx       #soda_counters+8
                    blo       Loop_2              ;repeat for all counters
                    staa      LED                 ;update the LED accordingly
                    rts

;*******************************************************************************

AllowOneDrinkOnly   
                    pshx
                    pshb
                    psha

                    ldx       #8                  ;number of bits in a byte
                    clrb                          ;initialize bit counter
Loop_3              lsra                          ;drink choice into CCR[C]
                    bcc       Cont_2              ;skip zeros
                    incb                          ;count this choice
Cont_2              dex                           ;one less bit to ess
                    bne       Loop_3              ;repeat for all bits

                    cmpb      #1                  ;do we have only one drink?
                    bls       Done_1             ;if so, we're done

                    pula
                    clra                          ;else zero caller's RegA (drinks)
                    psha

Done_1              pula
                    pulb
                    pulx
                    rts

;*******************************************************************************

PulseDelay          
                    psha
                    clra
Loop_4              deca
                    bne       Loop_4
                    pula
                    rts

;*******************************************************************************

IRQ_Handler         
                    ldd       money_total         ;D = available money
                    cpd       #DRINK_COST         ;is it enough for a drink?
                    blo       Done_2             ;if less, ignore request

                    ldaa      SODA_CHOICE         ;A = drink choice
                    bsr       AllowOneDrinkOnly   ;A = validated drink choice (zero if more than one)
                    bita      LED                 ;is the drink available (LED on)?
                    beq       Done_2              ;if not, ignore request
          ;-------------------------------------- ;deliver drink
                    staa      SODA_PULSES         ;start selected drink pulse
                    bsr       PulseDelay          ;arbitrary delay for the pulse
                    clr       SODA_PULSES         ;stop all drink pulses
          ;-------------------------------------- ;count down the available drinks
                    ldx       #soda_counters
Loop_5             lsra                          ;move choice into CCR[C]
                    bcc       Cont_3             ;if not this one, continue
                    dec       ,x                  ;one less drink
                    ldd       money_total         ;D = previous money balance
                    subd      #DRINK_COST         ;less the drink value
                    std       money_total         ;update money balance
                    ldx       #soda_counters+8 ;will cause termination of loop (by making X too large)
Cont_3              inx
                    cpx       #soda_counters+8
                    blo       Loop_5
                    bsr       AdjustLeds          ;adjust LED indicators
          ;--------------------------------------
Done_2              rti

;*******************************************************************************

XIRQ_Handler        
                    ldab      COIN                ;B = value of inserted coin

                    cmpb      #1                  ;1 is allowed value
                    beq       Accept_1

                    cmpb      #2                  ;2 is allowed value
                    beq       Accept_1

                    cmpb      #5                  ;5 is allowed value
                    beq       Accept_1

                    cmpb      #10                 ;10 is allowed value
                    beq       Accept_1

          ; What do we do with all other coins?

                    bra       Done_3              ;get out of here
          ;-------------------------------------- ;update money in machine
Accept_1            clra
                    addd      money_total         ;add inserted money to total
                    bcs       Done_3              ;on (unlikely) overflow, ignore
                    std       money_total
          ;--------------------------------------
Done_3              rti

;*******************************************************************************
                    org       Virq
                    dw        IRQ_Handler

                    org       Vxirq
                    dw        XIRQ_Handler

                    org       Vreset
                    dw        Start
;*******************************************************************************

错误:

好的,就在这里,完全未经测试,但应该给你想法!

假设:IRQ 输入是去抖动的,IRQ 是边沿触发的(因此不会重复同一个按键),XIRQ 脉冲将比执行相应处理程序所需的时间短,以避免计数同样的钱两次或更多。

正如我在评论中所说,设计存在一些缺陷,但如果我们忽略这一点并假设极端情况不会发生,那么有一种可能性:

    ;*******************************************************************************
; MCU specific
;*******************************************************************************

REGS                equ       00               ;register base
PORTB               equ       REGS+            ;port B (output only)
PORTC               equ       REGS+            ;port C
OPTION              equ       REGS+            ;System Configuration Options
STACKTOP            equ       FF               ;Top of Stack
RAM                 equ       [=10=]40               ;beginning of RAM
ROM                 equ       $F800               ;beginning of ROM

Virq                def       $FFF2               ;IRQ vector
Vxirq               def       $FFF4               ;XIRQ vector
Vreset              equ       $FFFE               ;reset vector

X.                  equ       %01000000           ;XIRQ disable
IRQE.               equ       %00100000           ;IRQ Edge sensitive

;*******************************************************************************
; Application specific
;*******************************************************************************

LED                 equ       PORTB               ;bitmap of LED
COIN                equ       PORTC               ;coin value is here
SODA_CHOICE         equ       PORTC               ;drink choice as bitmap
SODA_PULSES         equ       [=10=]80               ;bitmap of soda pulses

INITIAL_DRINKS      equ       4                   ;number of initial drinks
DRINK_COST          equ       20                  ;drink cost in dollars

NOT                 equ       $FF                 ;XOR value to invert bits
;*******************************************************************************
                    org       RAM
;*******************************************************************************

soda_counters       rmb       8                   ;array of soda counters
money_total         rmb       2                   ;keeps money in machine

;*******************************************************************************
                    org       ROM
;*******************************************************************************

Start               proc
                    lds       #STACKTOP
                    bsr       InitMachine

                    tpa
                    anda      #X.^NOT             ;enable XIRQ interrupts
                    tap

                    lda       OPTION
                    ora       #IRQE.              ;make IRQ edge sensitive
                    sta       OPTION

Loop@@              cli                           ;enable interrupts
                    wai                           ;low power mode until interrupt
                    bra       Loop@@              ;endless loop (all work is done in interrupt handlers)

;*******************************************************************************

InitMachine         proc
          ;-------------------------------------- ;assume INITIAL_DRINKS of each type
                    ldx       #soda_counters      ;X -> drink counters
                    ldaa      #INITIAL_DRINKS     ;A = number of drinks initially
Loop@@              staa      ,x                  ;update current counter
                    inx                           ;X -> next drink counter
                    cpx       #soda_counters+::soda_counters
                    blo       Loop@@              ;repeat for all drink counters
                    bsr       AdjustLeds          ;adjust LED indicators
          ;--------------------------------------
                    clra
                    clrb
                    std       money_total         ;zero initial money balance
                    rts

;*******************************************************************************

AdjustLeds          proc
                    ldx       #soda_counters      ;X -> soda counters
                    clra                          ;bit mask of soda LED
Loop@@              tst       ,x                  ;test current soda counter
                    clc                           ;assume a zero
                    beq       Cont@@              ;if zero, go put a zero in the mask
                    sec                           ;else we'll put a one in the mask
Cont@@              rora                          ;shift in zero/one bit for this LED
                    inx                           ;X -> next soda counter
                    cpx       #soda_counters+::soda_counters
                    blo       Loop@@              ;repeat for all counters
                    staa      LED                 ;update the LED accordingly
                    rts

;*******************************************************************************

AllowOneDrinkOnly   proc
                    pshx
                    pshb
                    psha

                    ldx       #8                  ;number of bits in a byte
                    clrb                          ;initialize bit counter
Loop@@              lsra                          ;drink choice into CCR[C]
                    bcc       Cont@@              ;skip zeros
                    incb                          ;count this choice
Cont@@              dex                           ;one less bit to process
                    bne       Loop@@              ;repeat for all bits

                    cmpb      #1                  ;do we have only one drink?
                    bls       Done@@              ;if so, we're done

                    pula
                    clra                          ;else zero caller's RegA (drinks)
                    psha

Done@@              pula
                    pulb
                    pulx
                    rts

;*******************************************************************************

PulseDelay          proc
                    psha
                    clra
Loop@@              deca
                    bne       Loop@@
                    pula
                    rts

;*******************************************************************************

IRQ_Handler         proc
                    ldd       money_total         ;D = available money
                    cpd       #DRINK_COST         ;is it enough for a drink?
                    blo       Done@@              ;if less, ignore request

                    ldaa      SODA_CHOICE         ;A = drink choice
                    bsr       AllowOneDrinkOnly   ;A = validated drink choice (zero if more than one)
                    bita      LED                 ;is the drink available (LED on)?
                    beq       Done@@              ;if not, ignore request
          ;-------------------------------------- ;deliver drink
                    staa      SODA_PULSES         ;start selected drink pulse
                    bsr       PulseDelay          ;arbitrary delay for the pulse
                    clr       SODA_PULSES         ;stop all drink pulses
          ;-------------------------------------- ;count down the available drinks
                    ldx       #soda_counters
Loop@@              lsra                          ;move choice into CCR[C]
                    bcc       Cont@@              ;if not this one, continue
                    dec       ,x                  ;one less drink
                    ldd       money_total         ;D = previous money balance
                    subd      #DRINK_COST         ;less the drink value
                    std       money_total         ;update money balance
                    ldx       #soda_counters+::soda_counters ;will cause termination of loop (by making X too large)
Cont@@              inx
                    cpx       #soda_counters+::soda_counters
                    blo       Loop@@
                    bsr       AdjustLeds          ;adjust LED indicators
          ;--------------------------------------
Done@@              rti

;*******************************************************************************

XIRQ_Handler        proc
                    ldab      COIN                ;B = value of inserted coin

                    cmpb      #1                  ;1 is allowed value
                    beq       Accept@@

                    cmpb      #2                  ;2 is allowed value
                    beq       Accept@@

                    cmpb      #5                  ;5 is allowed value
                    beq       Accept@@

                    cmpb      #10                 ;10 is allowed value
                    beq       Accept@@

          ; What do we do with all other coins?

                    bra       Done@@              ;get out of here
          ;-------------------------------------- ;update money in machine
Accept@@            clra
                    addd      money_total         ;add inserted money to total
                    bcs       Done@@              ;on (unlikely) overflow, ignore
                    std       money_total
          ;--------------------------------------
Done@@              rti

;*******************************************************************************
                    org       Virq
                    dw        IRQ_Handler

                    org       Vxirq
                    dw        XIRQ_Handler

                    org       Vreset
                    dw        Start
;*******************************************************************************

现在,我想要一杯免费苏打水来工作:)