我一直在努力解决与 IRQ 相关的话题(中断本身);我正在使用旧的MC68HC11
练了一段时间;我决定继续检查本章中展示的最难的练习,这就是为什么我找到了一个有趣的练习(而且有点棘手)
看看这个:
这是我到目前为止所尝试的(这只是一个大纲):
注意:
FLAGNMI 表示 XIRQ
FLAGIQR 表示 IRQ
IRQ EQU $FFF2
XIRQ EQU $FFF4
RESET EQU $FFFE
RWM EQU $0000
ROM EQU $C000
LEDS EQU $1004
VARIABLE EQU $1003
MECHANICAL_SEAL EQU $0080
CONFIG EQU $1039
CLR VALUE
CLR BALANCE
CLR PRICE_SODA
TPA
ANDA #(MASKNMI&MASKIRQ)
TAP
LDAA CONFIG
ORAA #MASKEDGE
STAA CONFIG
CLR FLAGIRQ
CLR FLAGNMI
LDAA #$00
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 $1000 ;register base
PORTB equ REGS+$04 ;port B (output only)
PORTC equ REGS+$03 ;port C
OPTION equ REGS+$39 ;System Configuration Options
STACKTOP equ $01FF ;Top of Stack
RAM equ $0040 ;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 $0080 ;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
;*******************************************************************************
错误: