在汇编中使用Interupts

Nic*_*ick 4 assembly

我被要求用中断重写我的代码(完整说明).我们还没有真正涵盖课堂上的中断,我不确定如何使用它们或如何实现它们.这是我的代码,我写的不使用中断,基本上使键盘成为钢琴或可以播放一首为摩托罗拉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)

有人可以给我一个例子,说明如何有效地实现或只是提示如何开始编写中断,以便我可以用它们重写我的代码.

sea*_*son 5

要在hc11上使用中断,您需要做四件事:

  1. 首先确定要使用哪种中断.hc11有许多不同的类型,因此您必须参考手册,以获得适合您要执行的操作的手册.

对于接下来的步骤,我假设您正在使用IRQ中断.它只是hc11上的一个简单中断引脚,当电压降至低电平时会中断系统.但是,对于任何其他中断,步骤将非常相似.

  1. 您需要初始化中断服务例程的起始位置.当触发中断时,处理器将检查向量表以确定它需要去的位置.因此,例如当IRQ被触发时,它将转到对应于IRQ($ FFF2)的表条目,然后跳转到存储在那里的地址.我们将标记中断服务例程IRQ_INT并将其存储在与IRQ相对应的表条目中,以便在触发IRQ时它将开始在标签处执行代码IRQ_INT.

    ORG   $FFF2
    FDB   IRQ_INT
    
    Run Code Online (Sandbox Code Playgroud)
  2. 接下来,您需要启用中断,以便处理器在触发时识别它.您需要再次检查手册中的值以及存储该值的寄存器以启用它.要使能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)
  3. 最后,您需要编写中断服务程序.这是每次触发中断时将执行的代码.它将从我们先前在向量表中设置的标签开始,并在它到达指令时结束RTI.从中断返回指令告诉处理器服务程序已完成,它应该返回到触发中断之前执行的任何操作.

    IRQ_INT
           <instructions go here>
           RTI
    
    Run Code Online (Sandbox Code Playgroud)

我的猜测是你会想要键盘端口上的某种中断,当键被击中时会触发.一旦键被击中,中断将触发处理器进入中断服务程序.在那里,你必须编写代码来确定哪个键被击中并播放正确的音符.