熊谷研トップへ  マイコン関係目次へ

エンコーダのカウント1(U/D信号)
熊谷和志 2003年02月10日
最終更新 2005年03月04日


AKI-H8/3664Fは位相計数モードを備えておらず、エンコーダのA/B相信号を直接カウントすることができません。
ソフトウェア処理でカウントすることも可能ですが、U/D信号ならもっと簡単にカウントできます。
そこで、AVRマイコンでA/B信号をU/D信号に変換し、それを外部割り込みを利用してカウントしてみました。
関連ページ:エンコーダ信号変換器(AT90S2343)、エンコーダのカウント2(A/B相信号)

0.目次

 1.割り込み例外処理
  1.1 割り込み例外処理の概要
  1.2 外部割り込み
 2.プログラム
  2.1 カウントプログラム(アセンブリ言語)
  2.2 応用例
  2.3 テストプログラム
 3.タイマA
 4.SCI3
  4.1 関係レジスタ
  4.2 使用方法
 ○参考資料
 <更新履歴>

1.割り込み例外処理

1.1 割り込み例外処理の概要

H8/3664には以下の例外処理がある。

これらのうち、通常のプログラム実行状態で利用するのが割り込み例外処理である。
割り込み全般についての説明は参考書に譲り、ここではH8/3664の割り込み例外処理について説明する。

ベクタアドレス
例外処理へ移る方法として、テーブルを用いる手法がよく使われている。
H8シリーズでは、プログラム領域の先頭部分にアドレステーブルが置かれている。
このテーブル中の各アドレスのデータは、それぞれの例外処理の開始番地を指し示しているので、ベクタアドレスと呼ばれる。
例外処理への他の移行方法としては、Z80の割り込みモード2のように、割り込み要求デバイスから開始番地のデータ(割り込みベクタ)を受け取るものもある。

Z80やAVRなどでは、それぞれ決まった番地から処理を開始するという、プログラムカウンタ(PC)の値を変えるだけの単純な処理であるのに対し、H8では指定された位置からスタートアドレスのデータを読み込んだ後にPCの値を変えるという2段階の処理となっている。
もちろんこれは、CPUコアの設計思想の違いであり、高級低級という違いではない。

割り込み例外処理を利用する場合は、それぞれの処理に対して決められた位置に、処理開始番地を書いておく。

割り込み要求の制御
それぞれ割り込み要因が割り込み要求信号を発生するには

  1. 割り込み要因の発生(割り込み要求フラグ
  2. それぞれの割り込みの許可(割り込みイネーブルビット
の二つがそろうことが必要であり、通常、割り込みイネーブルビットによってそれぞれの制御を行う。
CPUが割り込み例外処理を行うにはさらに、
コンディションコードレジスタ(CCR)の割り込みマスクビット(I)=0
であることが必要である。
割り込みマスクビットは、リセット直後は1に初期化されるので、リセット直後は割り込みは受け付けられない状態である(NMIを除く)。
また、割り込みマスクビットは例外処理が開始されるときに自動的に1にセットされるので、何らかの例外処理が実行中の時は、他の例外処理は保留状態となる。

割り込みマスクビットはプログラム中で0にクリアできるので、例外処理実行中に他の割り込み例外処理を受け付けるといった制御も可能である。
H8/3048Fや3052Fなどでは、さらにUIビットも使った多重割り込み制御が可能である。

1.2 外部割り込み

H8/3664では外部割り込み端子として

と10本も用意されている。
WKP0〜5はベクタアドレスが独立していないので、端子に余裕がある場合はIRQ0〜3を使うことを勧める。

関係レジスタ
IRQに関係するレジスタは以下の通り。
 

アドレス 名称 略称 初期値
H'FFE0 ポートモードレジスタ1 PMR1 H'0C
H'FFF2 割り込みエッジセレクトレジスタ1 IEGR1 H'70
H'FFF4 割り込みイネーブルレジスタ1 IENR1 H'10
H'FFF6 割り込みフラグレジスタ1 IRR1 H'30

ポートモードレジスタ1(PMR1)
I/O関係レジスタで、端子機能切り替えを行う。
 

7 6 5 4 3 2 1 0
IRQ3 IRQ2 IRQ1 IRQ0 - - TXD TMOW
IRQ3:  0:汎用入出力(P17)、1:~IRQ3およびTRGV入力端子
IRQ2-0:0:汎用入出力(P16-14)、1:~IRQ入力端子
TXD:  0:汎用入出力(P22)、1:TxD出力端子
TMOW: 0:汎用入出力(P10)、1:TMOW出力端子
割り込みエッジセレクトレジスタ1(IEGR1)
立ち下がりエッジか立ち上がりエッジを選択(初期値:立ち下がりエッジ)
割り込みイネーブルレジスタ1(IENR1)
対応するビットを1にすることにより、それぞれの割り込み要求がイネーブルになる。
割り込みフラグレジスタ1(IRR1)
対応する割り込み要因が発生すると、それぞれのフラグが1になる。
割り込み例外処理が実行されても自動では0にクリアされないので、割り込み処理中(通常最初)にクリア命令を実行しなければならない。
使用手順
以下の手順で各レジスタを設定する。
  1. 使いたいIRQ端子を有効に(PMR1)
  2. エッジ選択(IEGR1)
  3. 割り込みイネーブル(IENR1)
IRQ信号のパルス幅はシステムクロックの2サイクル時間以上あればよい。

2.プログラム

2.1 カウントプログラム(アセンブリ言語) [ソースリスト(3664cntU.mar:TAB=8)]

RAM領域に変数を用意し、割り込み処理ルーチンでアップカウント/ダウンカウントすればよい。
H8/3048FのITU2の位相計数モードとの互換を考え、カウント変数は2bytesとした。
ソースリストで関係する部分を以下に示す。

;count routine using external interrupt signals
cnt0:   push.w  r0       ;count up
      bclr.b   #0,@irr1:8  ;IRRI0 clear   --割り込みフラグクリア
      mov.w   @_ENCNT,r0 ;get count
      inc.w   #1,r0               --カウントアップ(IRQ1ではカウントダウン)
      mov.w   r0,@_ENCNT ;store
      pop.w   r0
      rte
  :
      .section B,data,align=2 ;RAM area
_ENCNT: .res.w   1

C言語プログラムでは、ENCNTという変数名を外部参照すれば、ITU2のカウントレジスタ(TCNT2)と同様にエンコーダのカウント値を読み込むことができる。

この割り込み例外処理1回に要するステート数は53〜65であり、クロック周波数16MHzの場合、2000P/revのパルスをカウントする処理だけを行うとしても最高7384rpm程度と、限界はかなり低い。
もちろんA/B相信号を直接読み込み、ソフトウェア処理でカウントすることも可能であるが、パルス数が多い場合には、外部デバイスを使ってCPUの負担を減らすか、位相計数モードを備えたMCUを利用すべきである。

2.2 応用例

A/B相出力、500P/R、モータ最高回転数6210rpmのエンコーダ信号をカウントする。
パルス数が多いので、外部デバイスとしてAT90S2343を使用してCPUの負担を軽減する。
AT90S2343で4逓倍およびU/D信号に変換後、IRQを利用してカウントする。

AT90S2343の処理内容については「エンコーダ信号変換器」(AT90S2343)を参照願いたい。
パルス数が多いので、AT90S2343には4MHz以上の外部クロックの供給が必要である。
結線図を以下に示す。


図1 A/B相エンコーダのカウント

4MHzクロックの供給にはタイマAの分周クロック出力(TMOW)を利用した。
また、カウント値を、SCI3を用いて4桁のASCIIデータとして送出し、パソコン上のハイパーターミナル等で表示できるようにしてみた。
P11はAVRマイコンのリセット信号に使用しているだけであり、他のビットで構わない。

この応用例のプログラムは次節で説明する。

2.3 テストプログラム [ソースリスト(cnttestU.c:TAB=4)]

処理内容
以下の処理をしているだけの、簡単なプログラムである。

  1. U/D信号を割り込み処理でカウント(ENCNT)
  2. SCI3を用いて4桁のASCIIデータとして送出
SCI3関係の関数は、「A/D、D/A、SCIをまとめてテストする」(H8/3048F)で使用したものをSCI3用に少し手直ししただけである。
SCI3については4章で詳述する。

これでハイパーターミナルを起動すると、4桁の16進データが流れながら表示される。

初期化の手順
外部デバイスとして使用しているAT90S2343を考慮し、以下の手順で初期化を行っている。

  1. AT90S2343用クロック発生
  2. AT90S2343リセット
  3. AT90S2343起動完了まで待機
  4. 外部割り込み有効化
これにI/O、SCI3の初期化を織り込んでいる。
AT90S2343のリセット信号保持で約0.05ms、起動完了待機で約3.7msのウェイトを念のために取っている。

なお、スタートアップルーチンもリンクする必要があるので、3664cntU.marをアセンブルして3664cntU.objを開発ツールフォルダに置き、以下のようにコンパイル&リンクすればよい。
3664cc cnttestU st3664 3664cntU

3.タイマA

H8/3664に内蔵されているタイマAは、インターバルタイマ/時計用タイムベースとして使用できる8ビットのタイマである。
また、TMOW端子から分周クロックを出力可能となっている。
タイマ機能とTMOW出力の設定は分かれており、二つの異なる機能の設定を一つのレジスタで行っている、と考えた方がよい。

タイマAのカウンタレジスタTCAはリードしかできないので、決められたインターバルしか設定できないことに注意が必要である。
タイマオーバーフロー割り込みを使用することで、一定間隔で割り込み例外処理を起動することができる。
レジスタ構成は以下の通り。
 

アドレス 名称 略称 初期値
H'FFA6 タイマモードレジスタA TMA H'10
H'FFA7 タイマカウンタA TCA H'00

TMA
 

7 6 5 4 3 2 1 0
TMA7 TMA6 TMA5 - TMA3 TMA2 TMA1 TMA0
TMA7-5:アウトプットセレクト(TMOW端子から出力するクロックを選択)
TMA3:インターナルクロックセレクト3(タイマAの動作モードを選択)
TMA2-0:インターナルクロックセレクト(クロックの分周値を選択)
      TMA3=1のとき、1XXでTCAリセット(PSWもリセット)
インターバル動作
TMA3=0で動作。
動作クロックはTMA2-0で選択する(下表)。
割り込みイネーブルレジスタ1(IENR1:上述)のIENTAを1にセットすることでオーバーフロー割り込みを利用できる。

時計用タームベース動作
TMA3=1で動作。
割り込みイネーブルレジスタ1(IENR1:上述)のIENTAを1にセットすることでオーバーフロー割り込みを利用できる。
オーバーフロー周期はTMA2-0で選択し、000:1s、001:0.5s、010:0.25s、011:0.03125s、1XX:リセット、である。

クロック出力
ポートモードレジスタ1(PMR1:上述)のTMOWを1にセットすると、TMOW端子からクロックが出力される。
出力されるクロックはTMA7-5で選択する(下表)。
なお、出力としてサブクロックの分周値を利用する場合は、TMA3とTMA2を同時に1にしてはならない。
 

TMA7-5
TMOW
TMA2-0
TCA
000
φ/32
000
φ/8142
001
φ/16
001
φ/4096
010
φ/8
010
φ/2048
011
φ/4
011
φ/512
100
φW/32
100
φ/256
101
φW/16
101
φ/128
110
φW/8
110
φ/32
111
φW/4
111
φ/8
φ:システムクロック、φW:サブクロック(32.768kHz)

4.SCI3

H8/3664は1チャネルのシリアルコミュニケーションインタフェース(SCI3)を内蔵している。
機能としては、スマートカードインタフェース機能が無いことを除けば、H8/3048Fや3052Fに内蔵のSCIとほぼ同じであり、フラグクリアの条件が改善されているのみである。
H8/3048FのSCIについては「A/D、D/A、SCIをまとめてテストする」(H8/3048F)を参照願いたい。

このページでは、H8/3664のSCI3に特有の部分について説明する。

4.1 関係レジスタ

レジスタ構成は以下の通り。
ポートモードレジスタ1(PMR1)については上述の説明を参照願いたい。
 

アドレス 名称 略称 初期値
H'FFE0 ポートモードレジスタ1
PMR1
H'0C
H'FFA8 シリアルモードレジスタ SMR H'00
H'FFA9 ビットレートレジスタ BRR H'FF
H'FFAA シリアルコントロールレジスタ3 SCR3 H'00
H'FFAB トランスミットデータレジスタ TDR H'FF
H'FFAC
シリアルステータスレジスタ
SSR
H'80
H'FFAD
レシーブデータレジスタ
RDR
H'00

SMR
 

7 6 5 4 3 2 1 0
COM CHR PE PM STOP MP CKS1 CKS0
ビット名がH8/3048Fと少し異なるだけで、機能は同じ
SCR3
機能はH8/3048FのSCRと同じ
SSR
 
7 6 5 4 3 2 1 0
TDRE RDRF ORER FER PER TEND MPB MPBT
ビット名はH8/3048Fと同じ
機能も、TDRE、RDRF、TEND以外は同じ

H8/3048FではDMA以外ではデータをリード/ライトしてもTDRE、RDRF、TENDは変化しないが、H8/3664では
TDRへのライトおよびRDRからのリードでこれらのフラグが変化する。

4.2 使用方法

調歩同期式、19200ボー、8ビットデータ、パリティなし、ストップビット長1の場合を例にとる。

I.初期設定
SMRの設定は、COM=0、CHR=0、PE=0、PM=x、STOP=0、MP=0、CKS1,0=00 -> H'00。
BRRの設定は、BRR=25
初期化手順は以下の通り。

  1. SCRのビット7〜2をクリア、CKS1,0=00 -> SCR=H'00。
  2. SMRを設定(SMR=0
  3. BRRを設定(BRR=25)
  4. 1ビット期間以上待つ(シフトレジスタへのクロック印加待ち)
  5. PMR1のTXDを設定(TXD=1)
  6. SCRのTE、REをセット(SCR=H'30)
II.送信手順
全二重通信なので、送信関係のフラグだけをチェックすればよい。
送信手順は以下の通り。
H8/3048Fと違い、TDREのクリア(およびTENDのクリア)は不要である。
  1. 未送信のデータがなくなるまで待つ(SSRのビット7(TDRE)->1)
  2. 送信データレジスタ(TDR)に送信データをセットする。
III.受信手順
受信に関係するフラグは、RDRF、ORER、FER、PERの4つであるので、これらをチェックする。
どれもセットされていなければ、データは受信していない。
受信エラーが発生した場合の対処法はいくつかあるが、SCIに割り当てられている端子が少ないことを考えれば、多少のエラーは仕方がないと割り切るべきである。したがって、エラーが発生しても、フラグをクリアして以降の受信を継続する方法を採る。
受信手順は以下の通り。
H8/3048Fと違い、RDRFのクリアは不要である。
  1. SSRのビット6〜3(RDRF、ORER、FER、PER)のどれかが1になるのを待つ。
  2. RDRF=1であれば正常受信、0であれば受信エラー発生。
  3. 正常受信の場合、受信データレジスタ(RDR)よりデータを取り出す。
  4. 受信エラーの場合、エラーフラグをクリアする。
受信エラーの場合、エラー発生が分かるように、戻り値にH'FFをセットするのも一方法である。

○参考資料

以下のページ等を参考にした。

H8/3664シリーズハードウェアマニュアル (ルネサス)
<更新履歴>
2005/03/04 スタートアップルーチン改版による微更新
2003/02/10 初版


ページトップへ戻る

ご意見、ご指摘は熊谷:ckuma◎sendai-nct.ac.jp (◎は@)まで。