例題2.3LED 点灯 ->1 -> 消灯


LED(ポート5のbit0)が点灯しその後1秒たつと消灯するプログラムを書いてみましょう. ここでは,初めてサブルーチンが出てきます.サブルーチンへのジャンプの仕方,戻り方を学習します.
;      LEDONOFF.SRC          (c)yas@E-SYS Lab.
;**********************************
;*     LED点灯/消灯プログラム     *
;**********************************
;
;CPUの指定からI/Oの初期設定までは前回までに説明したとおりです.
;わからない場合は課題1,2を見返してください.
;
;------CPUの指定-------
        .CPU      300HA
;
;----シンボルの定義------
P5DR    .EQU      H'FFFFCA                  ;ポート5データレジスタ
LED1    .BEQU     0,P5DR                    ;ポート5のbit0をLED1で表す
LED2    .BEQU     1,P5DR                    ;ポート5のbit1をLED2で表す
        .SECTION  ROM,CODE,LOCATE=H'000100  ;セクションの宣言
;
;-----I/Oの初期設定----
INIT:   MOV.L     #H'FFFF10,ER7             ;スタックポインタの設定
        MOV.B     #H'FF,R0L                 ;ポート5を出力に設定するため
        MOV.B     R0L,@H'FFFFC8             ;ポート5DDRにH'FFを書き込む
;
;----MAINルーチン-----
;これよりメインです.
;今回はサブルーチンに飛んでいるので注意が必要です.
;プログラムの流れは,
;LED点灯→1秒待つ→LED消灯→LOOPラベルへ飛ぶ(無限ループ)
;となります.
;この1秒待つ部分がサブルーチンです.
;JSR命令でサブルーチンへと飛んで行き,
;サブルーチンが終わるとRTS命令で戻ってきます.
;タイマサブルーチンにあるTIME00ラベルから3行が
;このJSRのところにそのまますっぽり入っていると
;考えてください.
;
        BSET      LED2
LEDON:  BSET      LED1                      ;LED1を点灯する
        (___)     @TIME00                   ;1秒間待つ
LEDOFF: BCLR      LED1                      ;LED1を消灯する
LOOP:   JMP       @LOOP                     ;ここでループする
;
;----タイマサブルーチン------
;1秒間待つサブルーチンです.
;この部分の流れを説明します.
;メインからJSR命令で飛んできたらまず,汎用レジスタ(ER6:32bit)に
;H'280000を書き込みます.
;次に,ER6から1を減算します.
;ER6が0になったかチェックします(BNE).
;ER6が0でなかったら再び1を減算します.
;ER6が0になったらBNEの次の行,つまりRTS命令が実行され,
;サブルーチンに飛ぶ前の部分に帰ります.
;
;ここではH'280000回(16進数で28000回)減算処理が行われ,その時間が浪費される.
;つまり,この部分でプログラムが一定時間(約1秒)とまるわけです.
;
;また,TIME00以下3行は,C言語で言うところのfor文にあたり,
;ER6レジスタを変数iに置き換えると,
;for( i=H'280000 ; i!=0 ; i-- )
;に相当します.
;
;約1秒間のタイマ
;
TIME00: MOV.L     #H'280000,ER6             ;ER6にH'280000を書き込み
TIME01: SUB.L     #1,(___)                  ;1ずつ減算
        BNE       TIME01                    ;0になるまで減算を繰り返す
        (___)                               ;元のルーチンに戻る
;
        .END

課題 2.3の説明

  • 10行目:CPUの指定をしています.
  • 13〜15行目:シンボルの定義.ポート5データレジスタをP5DR,bit0をそれぞれLED1と表しました.
  • 16行目:セクションの宣言をしています.
  • 19〜21行目:初期設定,スタックポインタにH'FFF10を書き込んでいます.ポート5を出力に設定しています.P5DDR(ポート5データディレクションレジスタ)に所定の制御コードを書き込みます.付録からP5DDRの番地はH'FFFFC8であることが分かりますから,その番地に,出力ビットに設定したいので1を書き込みます.
  • 36〜40行目:LED1(P5DRのbit0)0をセットします.LED1を点灯します.その後“(___) @TIME00”でWAITサブルーチンに飛び,約1秒後にサブルーチンを抜けメインルーチンに戻ります.“BSET LED1”でLED1(P5DRのbit0)を1にセットします.つまり,LED1を消灯します.その後LOOPに飛ぶように指示されているので,LOOPで無限ループとなります.
  • 63〜66行目:WAITのサブルーチンです.H'200000から値を1ずつ引いていき,ゼロになるまでこの作業を繰り返します.この作業で約1秒間WAITとなり,値がゼロになったらメインルーチンに戻ります

TIME00: MOV.L #H'200000,ER6 ;約1秒間のタイマ

TIME01: SUB.L #1,ER6 ;ER6にH'200000を書き込み1ずつ減算

BNE TIME01 ;0になるまで減算を繰り返す

RTS ;元のルーチンに戻る

プログラムの上記の部分は for文とよく似ています.for文は初期値から設定条件下でプログラムを繰り返すループです.そして,for文は次のように構成されていました.

for(式1;式2;式3)

{繰り返したいプログラム}

for文では,まず式1(初期値),式2(条件)を行い,その次に繰り返したいプログラムを行い,式3を行っていました.

今回のプログラムでは,(式 1)H'200000(初期値)をER6にいれ,それからから1を引き算して(繰り返したいプログラム),ゼロ(式2(条件))になるまで,待ちを続けるループです.

今回新たに使われたニモニック

JSR

サブルーチンにとびます. RTSで戻ってきます
Ex) JSR @TIME00 ;@TIME00にとびます

SUB

第2オペランドから第1オペランドの内容を減算し,その結果を第2オペランドに格納します.
Ex) SUB.L #1,ER6 ;ER6からH'1を減算し,ER6に戻します

BNE

Zフラグが0なら指定されたところへ,Zフラグが1なら次の命令に進みます.
Ex) BNE TIME01 ;Zフラグ=0ならTIME01,Zフラグ=1なら次の命令へ進む

RTS

サブルーチンから復帰します
Ex) RTS ;元のルーチンに戻ります

 



[山口研究室] <back | index | next >