4

以下のコードを割り込み(完全な手順)で書き直すように求められます。クラスで割り込みについてはあまり説明していません。割り込みがどのように使用され、どのように実装されるのか正確にはわかりません。これは、基本的にキーボードをピアノにしたり、モトローラ 68hc11用に書かれた曲 (lamb、chromsc、hall) を演奏したりできる割り込みを使用せずに書いたコードです。

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  ;;;;;;;;;;

効果的に実装する方法の例、または割り込みのコーディングを開始する方法のヒントを教えてください。割り込みを使用してコードを書き直すことができます。

4

2 に答える 2

5

hc11 で割り込みを使用するには、次の 4 つのことを行う必要があります。

  1. まず、使用する割り込みの種類を決定します。hc11 にはさまざまなタイプがあるため、目的に適したタイプのマニュアルを参照する必要があります。

次の手順では、IRQ 割り込みを使用していると仮定します。電圧が低くなったときにシステムを中断するのは、hc11 の単純な割り込みピンです。ただし、手順は他の割り込みでも非常に似ています。

  1. 割り込みサービス ルーチンの開始位置を初期化する必要があります。割り込みがトリガーされると、プロセッサはベクタテーブルをチェックして、どこに行く必要があるかを判断します。たとえば、IRQ がトリガーされると、IRQ ($FFF2) に対応するテーブル エントリに移動し、そこに格納されているアドレスにジャンプします。割り込みサービス ルーチンIRQ_INTにラベルを付けて、IRQ に対応するテーブル エントリに格納し、IRQ がトリガーされたときにラベルでコードの実行を開始するようにしますIRQ_INT

    ORG   $FFF2
    FDB   IRQ_INT
    
  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
    
  3. 最後に、割り込みサービス ルーチンを作成する必要があります。これは、割り込みがトリガーされるたびに実行されるコードです。これは、ベクター テーブルで以前に設定したラベルから始まり、命令にヒットしたときに終了しますRTI。return from interrupt 命令は、サービスルーチンが終了し、割り込みがトリガーされる前に実行していたものに戻る必要があることをプロセッサに伝えます。

    IRQ_INT
           <instructions go here>
           RTI
    

私の推測では、キーが押されたときにトリガーされるキーボード ポートで何らかの割り込みが必要になると思います。キーが押されると、割り込みによってプロセッサが割り込みサービス ルーチンに移動します。そこでは、どのキーが打たれたかを判断し、適切な音符を演奏するコードを作成する必要があります。

于 2012-04-25T22:09:52.487 に答える
2

基本的にサブルーチンである 2 つの ISR を作成する必要があります。それぞれがタイマーによってトリガーされるハードウェア割り込みのようです。

1 つの isr は、スピーカー トーンをトグルし、それ自体 (オン/オフ) をトリガーして、N 期間のトーンを生成するものです。まず、タイマー TOC3 のプログラミング方法を理解することに慣れてください。

もう 1 つは、1 ミリ秒ごとに入力を探し、RDRF フラグを監視し、以前に行った以前のプロジェクトを介してデータを読み取るタイマー int ループです。TOC2 のプログラミングに慣れる

ISR を初期化する必要があります。つまり、CPU をセットアップして、ISR ルーチンがどこにあるかを伝える必要があります。あなたの指示は、TOC3 でこれを行う方法を示しており、TOC2 に似ているはずです。配布資料を読んで、toc2 の jmp テーブルがどこにあるかを確認してください。彼は toc3 の場所を教えてくれました。

 Memory $FFE4 contains 
 $00D9, so insert a JMP XXXX instruction at $00D9 (where XXXX is the 
 address of your TOC3 service routine.  Note: the opcode for JMP is $7E. 

次のようにします。

 org $00d9 
 jmp YourTOC3ISR

;;;;;;;;;;;;; メインルーチン

 initialize timer registers ie setup toc2 and toc3
 initialize interrupt registers

 2) Read the current Timer Count from TCNT (pg. 374), add your DELAY to it, 
 and store the result in TOC3 (pg. 409).  This defines when you want the 
 first interrupt to occur.
 3) Set OC3I bit in TMSK1 to enable TOC3 interrupts (pg. 410).
 4) Clear the OC3F bit in TFLG1 to clear any previous interrupt condition.
 (pg. 410).  IMPORTANT!!!  Note that you must write a 1 to this bit to 
 clear it!  Do not use BSET!  See the discussion on page 387.
 5) Optional: Write to OM3 and OL3 bits in TCTL1 register to define how the 
 OC3 output pin will behave when the interrupt occurs (pg. 412).
 6) Enable interrupts globally. (See SEI and CLI instructions.)


 do lab 7 code

;;;;;;;;;;;;;;;; toc3 isr ルーチン YourTOC3Isr, playtone ?

  save the regs and flags

 1) Define when the next interrupt should occur by adding your DELAY to TOC3.
 2) Do whatever it is you want done in the service routine ie speaker togggle stuff
 3) Clear the OC3F bit in TFLG1 to clear the interrupt condition (SEE ABOVE).
4) Return from interrupt when done (pg. 181).
unsave reg and flags
rti

;;;;;;;;;;;;;; toc2 isrルーチン

reg とフラグを保存する

次に、RDRF フラグをチェックし、設定されていない場合は戻ります。設定されている場合、受信レジスタから文字を読み取り、送信レジスタに書き込み (古い putchar ルーチンを使用できます)、playtone を呼び出して割り込みから戻ります。

この部分は、他の割り込みルーチン toc3 を呼び出すように彼が望んでいるように聞こえるので、タイマーを開始する TOC3 制御レジスタに書き込むだけで、割り込みが自己処理する必要があります。

reg を保存せず、rti にフラグを立てる

これが役に立てば幸いです、M

于 2012-04-25T22:38:11.137 に答える