我被要求用中断重写我的代码(完整说明).我们还没有真正涵盖课堂上的中断,我不确定如何使用它们或如何实现它们.这是我的代码,我写的不使用中断,基本上使键盘成为钢琴或可以播放一首为摩托罗拉68hc11写的歌曲(羊,chromsc,大厅):
PORTA EQU $1000 ;The speaker port
SPEAKER EQU PORTA
SPEAKERBIT EQU %00100000
SCSR EQU $6400 ; Serial communications status register
SCDR EQU $6401 ; Serial communcations data register
TDRE EQU %00000010 ; mask for TDRE flag in SCSR
RDRF EQU %00000001 ; mask for RDRF flag in SCSR
ORG $8000; Place data at 8000
LAMB FCB 'trerttttrrrrtuuutrerttttrrtre',$00
CHROMSC FCB 'q2we4r5ty7u8i9op-[=]',$00
HALL FCB 'qwertet5w5r2rqwertetiutetu',$00
KEYMAP FDB 'q', 220, 758 ; A ;key, frequency, and 1/4 second "period"
FDB '2', 233, 715 ; A#
FDB 'w', 247, 675 ; B
FDB 'e', 262, 636 ; C
FDB '4', 277, 602 ; C#
FDB 'r', 294, 567 ; D
FDB '5', 311, 536 ; D#
FDB 't', 330, 505 ; E
FDB 'y', 349, 478 ; F
FDB '7', 370, 450 ; F#
FDB 'u', 392, 425 ; G
FDB '8', 415, 402 ; G#
FDB 'i', 440, 379 ; A
FDB '9', 466, 358 ; A#
FDB 'o', 494, 337 ; B
FDB 'p', 523, 319 ; C
FDB '-', 554, 301 ; C#
FDB '[', 587, 284 ; D
FDB '=', 622, 268 ; D#
FDB ']', 659, 253 ; E
FDB $00 ; Null termination character
PROMPT FCB $0D, 'Piano program - use QWERTY row to play notes', $0D, $00 ;Prompt String
ORG $8800
LDS #$DFFF
;;;;;;;;;; Main Start ;;;;;;;;;;
LDX #PROMPT
PSHX ;Push the argument to the stack
JSR printString ;Print the promp string
PULX
ALWAYS DES
JSR getChar ;Get a character from the keyboard
JSR putChar
PULA ;put the character in A
PSHA ;Push character to the stack
JSR playTone ;Play the tone
PULA
CMPA #'a'
BNE SKIPLAMB
LDX #HALL
PSHX
JSR playSong
PULX
SKIPLAMB CMPA #'s'
BNE BRAALW
LDX #LAMB
PSHX
JSR playSong
PULX
BRAALW BRA ALWAYS ;Loop to the top and continue playing
;;;;;;;;;; Main End ;;;;;;;;;;
;;;;;;;;;; playTone Start ;;;;;;;;;; Passed an ascii character and a length on the stack
playTone PSHB ;for transparency
PSHA
PSHX
PSHY
TSY ;make Y point to the top of the stack
LDAA 8,Y ;load A with the passed argument
LDX #KEYMAP ;make Y point to the KEYMAP
CBAALWAYS LDAB 1,X ;load B with the ascii value
BEQ EXITPT ;If current value is $00, end of table, no key match, exit routine
CBA ;Compare B to A
BEQ SKIPTESTS ;If value are equal, skip rest of test to play tone
XGDX
ADDD #6 ;Make X point to the next character to compare
XGDX
BRA CBAALWAYS ;Branch until the end of table is reached
SKIPTESTS LDD 2,X ;Load D with the frequency
LSRD ;Number of times to toggle the speaker in a 1/4 second
LSRD ;this shortens the tone to an 1/8 note
;LSRD ;this plays a 1/16 note
;LSRD ;this plays a 1/32 note
PERIODLOOP LDY 4,X ;Load Y with the delay between toggles
FREQLOOP DEY ;Decrement Y until it's 0
BNE FREQLOOP ;Branch until X is 0
PSHB ;preserve D
PSHA
LDAA PORTA ;Load A with the speaker
EORA #SPEAKERBIT ;Toggle the speaker bit
STAA PORTA ;Store back into the speaker
PULA ;restore D
PULB
SUBD #1 ;Decrement D
CPD #0 ;Compare D to 0
BNE PERIODLOOP ;Branch until D is 0
EXITPT PULY
PULX
PULA
PULB ;return the stack to normal
RTS ;return to the main program
;;;;;;;;;; playTone End ;;;;;;;;;;
;;;;;;;;;; playSong Start;;;;;;;;;;
playSong PSHB ;Reference is passed on the stack
PSHA ;Pushes for transparency
PSHX
PSHY
TSX
LDX 8,x ;Load X with the passed value
LOOPSTRING LDAA 0,X ;Load A with the ith character of the string
BEQ ENDPSTRING ;Skips to end of subroutine if current character is null character
PSHA ;Pass the argument in A to putChar
JSR playTone
INS ;Return the stack to normal
INX ;increments X to point to the next character
BRA LOOPSTRING
ENDPSTRING PULY
PULX
PULA
PULB
RTS
;;;;;;;;;; playSong End ;;;;;;;;;;
;;;;;;;;;; putChar start ;;;;;;;;;; Passed argument should be an ascii value
putChar PSHB ;is passed an argument on the stack
PSHA ;for transparency
PSHX
PSHY
TSY ;stack frame
LDX #SCSR ;Load in address of SCSR (Serial Communication Status Register)
GCWAIT BRCLR 0,X TDRE GCWAIT ;Loop
LDAA 8,Y ;Load A with the passed value
STAA SCDR ;Write A to the SCDR
PULY
PULX
PULA
PULB
RTS
;;;;;;;;;; putChar end ;;;;;;;;;;
;;;;;;;;;; getChar start ;;;;;;;;;; ascii value is returned
getChar PSHB ;No argument. Passes result back on the stack.
PSHA ;For transparency
PSHX
PSHY
TSY
LDX #SCSR ;Load in address of SCSR (Serial Communication Status Register)
PCWAIT BRCLR 0,X RDRF PCWAIT ;Loop when the
LDAA SCDR ;Load A with what's in the SCDR (should be the pressed key)
STAA 8,Y ;Store it to the stack to be passed back
PULY
PULX
PULA
PULB
RTS
;;;;;;;;;; getChar end ;;;;;;;;;;
;;;;;;;;;; printString start ;;;;;;;;;; argument passed on the stack in ascii
printString PSHB ;Reference is passed on the stack
PSHA ;Pushes for transparency
PSHX
PSHY
TSX
LDX 8,x ;Load X with the passed value
LOOPSTRING1 LDAA 0,X ;Load A with the ith character of the string
BEQ ENDPSTRING1 ;Skips to end of subroutine if current character is null character
PSHA ;Pass the argument in A to putChar
JSR putChar
INS ;Return the stack to normal
INX ;increments X to point to the next character
BRA LOOPSTRING1
ENDPSTRING1 PULY
PULX
PULA
PULB
RTS
;;;;;;;;;; printString end ;;;;;;;;;;
Run Code Online (Sandbox Code Playgroud)
有人可以给我一个例子,说明如何有效地实现或只是提示如何开始编写中断,以便我可以用它们重写我的代码.
要在hc11上使用中断,您需要做四件事:
对于接下来的步骤,我假设您正在使用IRQ中断.它只是hc11上的一个简单中断引脚,当电压降至低电平时会中断系统.但是,对于任何其他中断,步骤将非常相似.
您需要初始化中断服务例程的起始位置.当触发中断时,处理器将检查向量表以确定它需要去的位置.因此,例如当IRQ被触发时,它将转到对应于IRQ($ FFF2)的表条目,然后跳转到存储在那里的地址.我们将标记中断服务例程IRQ_INT并将其存储在与IRQ相对应的表条目中,以便在触发IRQ时它将开始在标签处执行代码IRQ_INT.
ORG $FFF2
FDB IRQ_INT
Run Code Online (Sandbox Code Playgroud)接下来,您需要启用中断,以便处理器在触发时识别它.您需要再次检查手册中的值以及存储该值的寄存器以启用它.要使能IRQ,必须在中断控制寄存器(INTCR)中将IRQ使能位(IRQEN)设置为1.然后可以使用该CLI命令启用它.
INTCR EQU $001E ;address of interrupt control register
INTCR_IN EQU $60 ;sets IRQEN bits
LDAA #INTCR_IN
STAA INTCR
CLI
Run Code Online (Sandbox Code Playgroud)最后,您需要编写中断服务程序.这是每次触发中断时将执行的代码.它将从我们先前在向量表中设置的标签开始,并在它到达指令时结束RTI.从中断返回指令告诉处理器服务程序已完成,它应该返回到触发中断之前执行的任何操作.
IRQ_INT
<instructions go here>
RTI
Run Code Online (Sandbox Code Playgroud)我的猜测是你会想要键盘端口上的某种中断,当键被击中时会触发.一旦键被击中,中断将触发处理器进入中断服务程序.在那里,你必须编写代码来确定哪个键被击中并播放正确的音符.
| 归档时间: |
|
| 查看次数: |
745 次 |
| 最近记录: |