例題5.2 ADSERI


A/D変換してbinary(2進数)とdecimal(10進数)のプログラム
電圧変化できるもの(調節できるもの)を使ってA/D変換が行われていることをコンピュータにシリアルを用いて確認します.(シリアルについての説明は省略します)
;       ADSERI.SRC     (c)yas@E-SYS Lab.

;******************************************
;*      A/D変換値(2進数&10進数)を     *
;*      シリアル通信でで送るプログラム   *
;******************************************

;今回はシリアル通信を使ってA/D変換データをパソコンに送信しています.
;A/D変換が実際に動いていることをパソコン上で確認してみてください.
;シリアル通信の詳細について学習したい人は参考書等で行ってください.
;

;------CPUの指定-------
        .CPU    300HA

;----シンボルの定義------
;------シリアル通信用---------------------------
SMR1           .EQU    H'FFFFB8       ;シリアルモードレジスタ1を指定する番地
BRR1           .EQU    H'FFFFB9       ;ビットレートレジスタ1を指定する番地
SCR1           .EQU    H'FFFFBA       ;シリアルコントロールレジスタ1を指定する番地
TE             .BEQU   5,SCR1         ;トランスミットイネーブル(SCR1のbit5)
TDR1           .EQU    H'FFFFBB       ;トランスミットデータレジスタ1を指定する番地
SSR1           .EQU    H'FFFFBC       ;シリアルステータスレジスタ1を指定する番地
TDRE           .BEQU   7,SSR1         ;トランスミットデータエンプティ(SSR1のBIT7)

;--------A/D変換データ記憶用RAM-----------------
AD_BIN  .EQU    H'FFEF10               ;A/D変換した2進数結果を格納するRAM領域のラベル
D_DATA  .EQU    H'FFEF20               ;表示用のデータを一時的に格納するRAM領域
AD_DEC  .EQU    H'FFEF40       ;A/D変換した10進数結果を格納するRAM領域のラベル

;--------A/D変換用-----------------
ADCSR          .EQU    H'FFFFE8       ;A/Dコントロール/ステータスレジスタの番地
ADST           .BEQU   5,ADCSR ;ADCSRのbit5,変換開始/停止を選択
ADF            .BEQU   7,ADCSR ;ADCSRのbit7,変換終了を示すフラグ
ADDRAH  .EQU    H'FFFFE0       ;A/D変換結果を入れる上位8bitレジスタの番地
ADDRAL  .EQU    H'FFFFE1       ;A/D変換結果を入れる下位8bitレジスタの番地 

        .SECTION ROM,CODE,LOCATE=H'000100             ;コードセクションの宣言

;-----初期設定-----------

INIT:   MOV.L   #H'FFF10,ER7           ;スタックポインタの設定

;-----シリアル部分の初期設定----------

        MOV.B   #H'00,R0L              ;R0LにH'00を書き込んでそれをSCR1,SMR1に転送
        MOV.B   R0L,@SCR1              ;RIE,TIE,TEIE,MPIE,TE,REを"0"に,クロックを選択
        MOV.B   R0L,@SMR1              ;送信フォーマット設定(調歩,8bit,NP,stop1bit)
        MOV.B   #51,R0L                ;ビットレート設定のためにBRR1に"#51"を書き込む
        MOV.B   R0L,@BRR1              ;この場合は9600bit/sに設定される
        JSR     @TIME10        ;1bit以上の期間待って初期化完了
        BSET    TE                     ;SCRのbit5を「1」にセット 

;-----MAIN---------
;プログラムの流れ
; 1:A/D変換を行う(変換値の10進数化も行う)
; 2:シリアル通信にて送信する
; 3:少し待つ
; 4: 1:へ戻る
;

START:  JSR     @AD            ;ADにジャンプ
        JSR     @SOUSIN        ;SOUSINにジャンプ
        JSR     @TIME00        ;WAIT
        JSR     @TIME00        ;WAIT
        JSR     @TIME00        ;WAIT
        BRA     START                  ;STARTにジャンプ

;---サブルーチン--------

;-----A/D変換----------
;A/D変換を行う部分です.具体的な説明をします.
; AD:〜ADFをクリアするところまでは前回述べました.
;その下のSHLR命令ですが,
;A/D変換値は16bit左詰で出てきます.これを右詰へとする操作です.
;電圧値変換以下では,
;A/D変換結果を10進数として1桁ずつ格納しています.
;これは,シリアル通信で送ったデータを表示するには1文字ずつ
;送信しなくてはならないためです.
;詳細は自習してください.

AD:     JSR     @TIME00        ;TIME00秒WAIT
        BSET    ADST                   ;ADSTに「1」をビットセットするA/D変換開始
ADEND:  BTST    ADF                    ;ADFをチェックA/D変換終了したか?
        BEQ     ADEND                  ;ADFが「1」なら変換終了,「0」ならADENDにジャンプ
        MOV.L   #0,ER1                 ;変換結果をいれるレジスタER1をクリア
        MOV.B   @ADDRAH,R1H    ;変換値の上位8bitをR1の上位へ
        MOV.B   @ADDRAL,R1L            ;変換値の下位2bitをR1の下位へ
        BCLR    ADF                    ;ADFを「0」にクリアする.
        SHLR.W  R1             ;R1を右側へ詰めるために右方向へ6bitシフト
        SHLR.W  R1
        SHLR.W  R1
        SHLR.W  R1
        SHLR.W  R1
        SHLR.W  R1
        MOV.W   R1,@AD_BIN             ;AD_BINにA/D変換値(2進数)を入れる
;-----電圧値変換-----
        MOV.W   #4883,R0               ;A/D変換値に4883を乗算して5V/10bit・FSに正規化する
        MULXU.W R0,ER1         ;5V/FS対応のディジタル値がER1へ

;----10進(アスキーコード)変換-----
        MOV.B   #7,R5L                 ;表示文字数をR5Lにセットする
        MOV.L   #AD_DEC+7,ER4  ;表示数値データの先頭番地をER4にセットする
DECI:   MOV.W   E1,R2                  ;2進数10進数変換開始,ER1上位16bitR2へ
        MOV.W   #10,R0                 ;R0に10をセット
        EXTU.L  ER2                    ;ER2をゼロ拡張し32bitにして
        DIVXU.W R0,ER2         ;ER2÷10を32bitで行う,商がR2に,余りがE2に入る
        MOV.W   E2,E1                  ;この余りをE1に戻す
        DIVXU.W R0,ER1         ;ER1÷10を32bitで行う.商がR1に,余りがE1に入る
        MOV.W   R2,E2                  ;前回の商をE2に転送
        MOV.W   R1,R2                  ;今回の商をR2に転送
        MOV.W   E1,R3                  ;余りをR3に入れる
        ADD.B   #H'30,R3L              ;H'30加算で10進→アスキーコード変換
        MOV.B   R3L,@-ER4              ;結果をRAMに格納
        MOV.L   ER2,ER1        ;下位桁の計算準備
        DEC.B   R5L                    ;セットした文字数から1を引く
        BNE     DECI                   ;文字数が0になるまでDECIへジャンプを繰り返す
        RTS                            ;元のルーチンに戻る 

;----シリアル通信にてパソコンに送信-----
;-----2進数を送信---------
;まず,2進数をパソコン上で表示します.
;カンマ(,)で区切った後,
;10進数を表示します.
;最後に改行(復帰&改行)します.
;
;シリアル通信で表示する部分はモジュール化してDISPという関数にしてあります.
;
SOUSIN: MOV.W   @AD_BIN,R1     ;R1にAD_BINのA/D変換値をいれる
        MOV.W   #1,R3                  ;R3に#1をいれる
BINH:   MOV.B   #H'30,R0H              ;R0HにH'30をいれる
        BTST    R3L,R1H        ;R1H=R3Lならば
        BEQ     NUMH                   ;NUMHにとぶ
        INC.B   R0H                    ;R0Hに+1
NUMH:   MOV.B   R0H,@D_DATA            ;D_DATAにR0Hをいれる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ
        SUB.W   #1,R3                  ;R3から1を減算
        BPL     BINH                   ;CCRの「N=0」ならBINHにとぶ
        MOV.W   #7,R3                  ;R3に#7を書き込む
BINL:   MOV.B   #H'30,R0H              ;R0HにH'30を書き込む
        BTST    R3L,R1L        ;R1LレジスタとR3Lをチェック
        BEQ     NUML                   ;同じならNUMLにとぶ
        INC.B   R0H                    ;R0Hに+1
NUML:   MOV.B   R0H,@D_DATA            ;
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ
        SUB.W   #1,R3                  ;R3からH'1減算
        BPL     BINL                   ;CCRの「N=0」ならBINLにとぶ 
;----カンマ送信-----
KANMA:  MOV.B   #H'2C,R0L      ;
        MOV.B   R0L,@D_DATA            ;D_DATAにH'2Cをいれる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ 
;----10進数送信-----
AD_D:   MOV.B   @AD_DEC,R0L            ;AD_DECに順に書き込んだ10進数を
        MOV.B   R0L,@D_DATA            ;ディスプレイに表示するためD_DATAに入れる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

        MOV.B   #".",R0L                       ; "."を
        MOV.B   R0L,@D_DATA            ;ディスプレイに表示するためD_DATAに入れる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ
        MOV.B   @AD_DEC+1,R0L  ;AD_DEC+1に順に書き込んだ10進数を
        MOV.B   R0L,@D_DATA            ;ディスプレイに表示するためD_DATAに入れる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

        MOV.B   @AD_DEC+2,R0L  ;AD_DEC+2に順に書き込んだ10進数を
        MOV.B   R0L,@D_DATA            ;ディスプレイに表示するためD_DATAに入れる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

        MOV.B   @AD_DEC+3,R0L  ;AD_DEC+3に書き込んだ10進数を
        MOV.B   R0L,@D_DATA            ;ディスプレイに表示するためD_DATAに入れる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

        MOV.B   #"V",R0L               ; "V"を
        MOV.B   R0L,@D_DATA            ;ディスプレイに表示するためD_DATAに入れる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

;----復帰改行-----
LF:     MOV.B   #H'0A,R0L              ;
        MOV.B   R0L,@D_DATA            ;D_DATAにH'0Aをいれる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

CR:     MOV.B   #H'0D,R0L              ;
        MOV.B   R0L,@D_DATA            ;D_DATAにH'0Dをいれる
        JSR     @DISP                  ;シリアル通信で送るための関数DISPにとぶ

D_END:  BTST    TDRE                   ;TDREの状態をチェック
        BEQ     D_END                  ;TDREが「0」ならばD_ENDにとぶ
        RTS                            ;元のルーチンに戻る

;----D_DATAに入っている情報をシリアルでパソコンに送信する関数-----
DISP:   BTST    TDRE                   ;TDREの状態をチェック
        BEQ     DISP                   ;TDREが「0」ならばDISPにとぶ
        MOV.B   @D_DATA,R0L            ;
        MOV.B   R0L,@TDR1              ;TDR1にD_DATAをいれる
        BCLR    TDRE                   ;TDREを「0」にクリアする
        RTS                            ;元のルーチンに戻る

;-----タイマ(WAIT)サブルーチン--------
TIME00: MOV.W   #H'FFFF,R0
TIME01: SUB.W   #1,R0                  ;R0にH' FFFFを書き込みH'1ずつ減算
        BNE     TIME01                 ;ゼロになるまでTIME01を繰り返す
        RTS                            ;元のルーチンに戻る

TIME10: MOV.W   #H'80,R6               ;
TIME11: SUB.W   #1,R6                  ;R6にH'80を書き込みH'1ずつ減算
        BNE     TIME11                 ;ゼロになるまでTIME11を繰り返す
        RTS                            ;元のルーチンに戻る
        .END  

課題 5.2の説明

  • 7行目:CPUの指定をしています.
  • 7〜29行目:シンボルの定義をしています.ポートBデータレジスタをPBDRで表します.AD_BINにRAM領域,A/D変換値の格納場所を設定します.A/Dコントロール/ステータスレジスタをADCSR,ADCSRのbit5,変換開始/停止を選択するA/DスタートをADST,ADCSRのbit7,変換終了を示すA/DフラグをADF,A/D変換結果を入れる上位8bitレジスタの番地をADDRAH,A/D変換結果を入れる下位8bitレジスタの番地をADDRAL,D/A(CH-0)に比変換データを入力する番地をDADR0,D/A(CH-0,1共通)コントロールレジスタの番地をDACRで表します.
  • 32行目:コードセクション宣言です.H'000100番地を先頭にしなさいという指示をしています.
  • 35行目:初期設定です.スタックポインタにH'FFF10を書き込んでいます.
  • 38〜44行目:シリアル部分の初期設定です.
  • 47〜52行目:56行のADにジャンプします.RTSで戻ってきたらSOUSHINにジャンプします.RTSで戻ってきたらWAITをとります.STARTにジャンプ(繰り返す)します.
  • 56,57行目:WAITします.A/DスタートADSTに「1」をビットセットし,A/D変換を開始します.
  • 58〜59行目:ビットテストBTSTでADF(A/Dフラグ)の状態をチェックします.前回述べたように,ADFが0ならZフラグを「1」にセットし,ADFが「1」ならZフラグを「0」にクリアします.A/D変換が終了すると,ADFには「1」が入ります.ブランチイコールBEQでコンディションコードレジスタのZフラグの状態を調べます.Zフラグがが「0」ならば次の命令に進み,「1」ならばADENDにジャンプします.A/D変換が終了したら,変換結果を入れるレジスタER1を「0」にクリアします.そして,変換後のデータ上位8bitをレジスタR1の上位(R1L)へいれ,変換後のデータ下位2bitをレジスタR1の下位(R1L)へいれます.A/DフラグADFを「0」にビットクリアします.現在,R1に入っているA/D変換値は16bit左詰の状態です.これをSHLRで右にずらし,右詰にします.結果をAD_BINに入れます.
  • 72〜73行目:A/D変換の結果を,最大値5Vを基準とした値に変換します.
  • 75〜91行目:2進数の値を10進数に変換し,元のルーチンに戻ります.
  • 93〜165行目:シリアル通信部分です.この部分についての説明はしません.興味のある人は調べてください.
  • 168〜176行目:WAITのサブルーチンです

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

INC

デスティネーションオペランドに 1を加算し結果を格納する.

Ex) INC.B R0H ;R0Hに1加算し,結果をR0Hに格納

DIVXU

割り算を行います.

Ex) DVXU.W  R0,ER2 ;ER2÷R0→ER2上位16bitに余り,下位16bitに商を格納

BPL

もし CCRのN=0ならば指定されているところにそうでなければ次に進む

Ex) BPL BINH ;CCRのNが「0」ならBINHにとぶ


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