[はじめに]
最近のマイコンにはかなりの製品にA/Dコンバータが内蔵されています。その殆どは8〜10ビット程度の分解能をもっています。しかし、10ビットの分解能だからと言って、それをフルに使う必要はありません。実際の応用の場面では8ビット以下で十分な場合もあります。
[要求仕様例]
A/Dコンバータの比較的簡単な応用として少ないキーの入力があります。具体的なハードウェアの構成としては「
マイコンでのキー・スイッチ入力(その2)」を対象にして、押されたスイッチをA/Dコンバータで検出します。押されたスイッチとそのときのA/Dコンバータの入力電圧は以下のようになっているものとします。
| 入力電圧 | | 押されたスイッチ |
| 0.8VDD以上 | | なし |
| 0.6〜0.8VDD | | SW4 |
| 0.4〜0.6VDD | | SW3 |
| 0.2〜0.4VDD | | SW2 |
| 0.2VDD以下 | | SW1 |
[処理の考え方]
スイッチを押したり、離したりする際の入力電圧の変化は緩やかです。付加されたコンデンサの容量を1000pF程度と考えると、電圧が安定するまでに数百μ秒程度かかります。
その間に、この方式では入力電圧が他のキー入力に該当する領域を横切って変化します。このときに誤検出をしないためには、単純に入力電圧だけで判断はできません。そこで、入力電圧が安定していることを判断する処理が必要になります。そこで、ノイズ対策を兼ねて、16回の変換分を平均することで有効な変換結果として、その変化も監視します。
コーヒーブレイク
使用するスイッチにはチャタリングが存在します。その影響を避けるには波形を鈍らせる必要があります。ここでは、電圧設定用の抵抗とアナログ入力のコンデンサによる時定数回路がこの機能を果たしています。そのため、この回路の時定数をあまり小さくできません。
ノイズ対策のためにA/D変換結果を複数回平均することでも同様の効果は考えられます。しかし、A/D変換の前段階でチャタリングの影響をできるだけ少なくしないと、変換結果は大きな誤差が発生する可能性があります。
また、他のチャネルでもA/D変換を行なう場合に、その動作に影響を与える可能性があります。このため、できるだけ時定数回路でチャタリングの影響を避けます。
|
このようにして得られた有効な変換結果から、キー入力を判断します。
[判断基準の設定]
具体的な判断基準を設定します。何も押されていない状態(0.9V
DD)からの電圧変化例を以下のグラフに示します。これから、約500μ秒ごとに判定したとすると、0.1V
DD以下の変化であれば目的の電圧の領域に入っていると判断できます。そこで、余裕をみて、V
DD/16以下の変化で判定することにします。
[使用するハードウェア]
ここでは、78K0S/KY1+を高速内蔵発振器の8MHzで動作させ、ANI0端子を用いて、A/D変換は変換時間28μ秒で使用します。結果は上位8ビットだけを使用します。
ウォッチドッグ・タイマは使用しないので、停止しておきます。
[プログラムの構成(概要)]
プログラムとしては、初期設定部とA/D変換完了割り込みによる処理部、メイン処理、キー入力の判定部から構成されます。
- 初期設定部
変数の初期化、ウォッチドッグ・タイマの停止、高速内蔵発振器で8MHz動作を行なうために電源電圧が4V以上になるのを待ち、A/Dや割り込みの初期化を行ないます。
- 割り込み処理部
全体の処理時間に影響を与えるので、できるだけ短い時間で処理する必要があります。そのため、できるだけ単純な処理とします。具体的には、A/D変換結果の上位8ビットを累積し、得られた結果(8ビットからの桁上げ)を使用して変化の検出を行ないます。(前回の値と同じなら有効フラグを0にすることで、結果を通知する。)
- メイン処理
メイン処理の中で、割り込み処理により得られた結果を確認して有効なキー入力があれば、キー入力の判定部を呼び出します。
- キー入力の判定部
得られた入力電圧から有効なキーをデコードし、対応した処理部にテーブルを用いて分岐します。
[プログラム例]
(1)使用する変数
以下のような変数を使用します。COUNTERは16回の累積をカウントするための変数で初期値(16)からカウントダウンして0になったら累積完了を示します。
DATALOGは変換結果を累積するための変数で、結果の判定は上位バイトだけを使用します。16回の累積を行なうことで、下位4ビットに値が入ります。
OLDDATAは前回の累積結果の上位バイトを格納します。この値と、今回の累積結果の上位バイトを比較することで、変化が安定したかを判定します。
DATAVALIDは変換結果が安定したことを示すフラグとなります。この値が0ならば、変換結果は安定していること(有効)を示します。
・変数部の定義
STACKTOP DSEG IHRAM
DS 20H ; スタック領域として32バイト確保
STACKP:
DATWORK DSEG SADDR
COUNTER: DS 1 ; 処理判定用カウンタ
DATALOG: DS 2 ; データ蓄積用
OLDDATA: DS 1 ; 前回のデータ用
; 有効なら下位4ビットに変換結果
DATAVALID: DS 1 ; 有効データフラグ(0:有効)
(2)初期化部
変数やハードウェアの初期化を行なうサブルーチンで構成されます。これらのサブルーチンをメイン処理からよびだすことで、初期化を行ないます。
ハードウェアの初期化としては、まず、ウォッチドッグ・タイマと低速内蔵発振器を停止し、電源電圧が4V以上になるのまで低電圧検出回路を用いて待ちます。電源が安定したら、クロックを8MHzのfRに設定します。
A/D変換はANI0チャネルを最低速(28マイクロ秒ごとに変換する/8MHz)で動作するように初期化します。
割り込みは要求フラグをクリアして、A/D変換完了の割り込みのマスクを解除します。A/D変換の起動とCPUの割り込み許可はメイン処理で行ないます。
・メインの初期化処理
スタック・ポインタを設定した後、初期化サブルーチンをコールして初期化を行ないます。
CSEG
START: MOVW AX,#STACKP
MOVW SP,AX
CALL !INITRAM ; RAMの初期化
CALL !POWERON ; 電源の立ち上がりを待つ
CALL !INITAD ; A/Dの初期化
CALL !INITINT ; 割り込み初期化
・初期化サブルーチンのプログラム例
;
; 変数の初期化
;
INITRAM:
MOV COUNTER,#16
MOV DATALOG,#0
MOV DATALOG+1,#0
MOV OLDDATA,#NOKEYV
MOV DATAVALID,#0FFH
RET
;
; 電源の立ち上がり待ち(4V以上になるのを待つ)
;
POWERON:
DI
MOV LVIS,#00 ; VLI=4V
MOV LVIM,#10000000b ; 低電圧検出開始
MOV PCC,#00 ; CPU clock is fx/4
MOV WDTM,#01110111b ; WDTを停止
SET1 LSRSTOP ; 低速内蔵発振器停止
MOV A,#50
PONLOOP:
DEC A
BNZ $PONLOOP ; 0.2ms待つ
PONLOOP2:
NOP
BT LVIF,$PONLOOP2 ; 電圧が4V以上まで待つ
MOV PPCC,#00 ; CPU clock is fx=fR
RET
;
; 割り込みの初期化
;
INITINT:
MOV IF0,#00 ; 割り込みをクリア
CLR1 ADMK ; A/D割り込みマスク解除
RET
;
; A/Dの初期化
;
INITAD:
MOV ADM,#00111001b ; 変換時間設定
MOV PMC2,#00000001b ; ANI0を使用
SET1 PM2.0 ; PM20は入力にしておく
MOV ADS,#0 ; ANI0を選択する
RET
(3)割り込み処理部
ここではA/D変換完了の割り込み以外は使用していないので、A/D変換完了以外の割り込みのベクタ・テーブルには何も処理しないで戻るようにダミーアドレス(DUMMY)を設定しておきます。
RSTVECT CSEG AT 0
DW START ;00:リセットスタート処理のベクタ
DW DUMMY ;02:
DW DUMMY ;04:
DW DUMMY ;06:INTLVI
DW DUMMY ;08:INTP0
DW DUMMY ;0A:INTP1
DW DUMMY ;0C:INTTMH1
DW DUMMY ;0E:INTTM000
DW DUMMY ;10:INTTM010
DW ADINT ;12:INTAD
A/D変換完了割り込み処理部は28μ秒ごとに実行されるので、できるだけ処理時間を短くします。
・処理フロー
処理フローを以下に示します。
・A/D変換完了処理のプログラム例
プログラムの例を以下に示します。この処理は通常は52クロックで処理を完了し、16回の累積が完了したときには30クロック追加され、82クロックで処理が完了します。
;
; A/D割り込み処理
;
ADINT:
PUSH AX ; 4:
MOV A,ADCRH ; 4:結果の上位8ビットを読む
ADD A,DATALOG ; 4:結果を累積
MOV DATALOG,A ; 4:
MOV A,#0 ; 6:
ADDC A,DATALOG+1 ; 4:
MOV DATALOG+1,A ; 4:累積結果を保存
DEC COUNTER ; 4:回数をカウントし、
BNZ $EXITADINT ; 6:16回未満なら抜ける
XCH A,OLDDATA ; 4:結果の更新
SUB A,OLDDATA ; 4:変化を検出
MOV DATAVALID,A ; 4:検出結果をフラグに設定
MOV DATALOG,#0 ; 6:累積結果をクリア
MOV DATALOG+1,#0 ; 6:
MOV COUNTER,#16 ; 6:カウンタを初期化
EXITADINT:
POP AX ; 4:
RETI ; 8:
DUMMY:
RETI ; 未定義の割り込みは無視
(4)キー入力判定処理
A/D変換完了の割り込み処理で得られた結果とフラグから、押されたスイッチを判定し、対応した処理部に分岐します。この程度の入力であれば、逐次比較した方がプログラムは短くなりますが、ここではテーブル参照を用いて処理しています。なお、キー入力がない場合だけは最初にチェックすることで、余分な解析を行なわないようにしています。
テーブルは各キー入力に対応した処理ルーチンのアドレス(SW1〜SW4、NOKEY)で構成しておき、A/D変換完了の割り込み処理で得られた結果を2倍してオフセットを計算し、HLレジスタをポインタとしてテーブルから処理アドレスをAXレジスタに読み出します。AXレジスタで示されるアドレスに分岐させることで各処理部に分岐します。
なお、各処理部からは「BR !命令」でメイン処理に戻るものとします。
・処理フロー
処理フローを以下に示します。
・プログラムの例
;
; キー入力確認開始
;
SET1 ADCS ; A/D変換動作開始
EI
MAINLOOP:
MOV A,OLDDATA ; 結果の読み出し
CMP A,#NOKEYV ; キー入力があるか?
BNC $NOKEY ; なければ抜ける
MOV A,DATAVALID ; 有効フラグを読み出し
AND A,A ; チェックして無効なら
BNZ $NOKEY ; 抜けて、他の処理へ
; キー入力チェック
; (OLDDATAに格納されたデータ(0〜15)に応じて処理ルーチンに分岐)
;
KEYCHECK:
MOV A,OLDDATA ; 有効データを読み出す
ADD A,A ; アドレス変換のため2倍
ADD A,#LOW KEYTABLE ; テーブル参照アドレス計算
MOV L,A
MOV A,#HIGH KEYTABLE
ADDC A,#0
MOV H,A ; ポインタをHLレジスタに
MOV A,[HL] ; 下位アドレスを得る
MOV X,A
MOV A,[HL+1] ; 上位アドレスを得る
BR AX ; 処理部へ分岐
;
; キー入力のデコード用アドレス・テーブル
;
KEYTABLE:
DW SW1 ; 0:
DW SW1 ; 1:
DW SW1 ; 2:
DW SW1 ; 3:0.19VDD
DW SW2 ; 4:0.25VDD
DW SW2 ; 5:
DW SW2 ; 6:0.38VDD
DW SW3 ; 7:0.44VDD
DW SW3 ; 8:
DW SW3 ; 9:0.56VDD
DW SW4 ;10:0.63VDD
DW SW4 ;11:
DW SW4 ;12:0.75VDD
DW NOKEY ;13:0.82VDD未使用
DW NOKEY ;14:未使用
DW NOKEY ;15:未使用
(5)その他の処理
低速内蔵発振器を停止させるために、オプションバイトを以下のように記述しておきます。
@@OPTB CSEG AT 0080H
DB 10011100b
DB 11111111b
END
(2006/03)