[H8-ML(4002)] :Re:位相計数カウンタについて
From: Shigeru Makino <mac@xxxxxxxxxxxxxx>
Date: 2003年10月08日(水)13時32分04秒
macです。

Heatman さん<heatman@xxxxxxxxxxxxx> wrote:

> >16bit以上に拡張したいときは、
> :
> >unsinged intとして、TCNT2を読み、
> >32767以上なら、アンダーフロー、
> >32767未満なら、オーバフロー、
> >として、適当な変数extを、
> >アンダーフローならext--
> >オーバフローなら、ext++
> 
> 通常時は、カウンタ値を適当な変数に移し
> オーバフロー、アンダーフローの場合は、
> 状態に応じて変数の値を増減すれば良いと
> いうことでよろしいのでしょうか?

カウンターはあくまでフリーランニングさせ、
カウンタにTCNT2にWriteはしません。

TIER2のOVIEを立てておき、
Interruptがかかったら、TSRを読み OVF = 0にした後、
TCNT2を読み、もし、TCNT2が、0x0002だったら、

w = (++ext << 16) | TCNT2;
もし、リセット後最初なら、
0x00010002が、その時点のカウンター値だと、
読めばよいということです。

しかし、この方法は、重大な欠陥を持っています。
TCNT2を読んだあと、
w = (++ext << 16) | TCNT2;
している間も、カウンターは動作し、
TCNT2は別の値になっている可能性があります。

そこで、割り込み直後、
t = TCNT2;
としてから、TSRを処理し、

w = (++ext << 16) | t;
if ( t < 0x8000) w = (++ext << 16) | t;
else  w = (--ext << 16) | t;

としたらどうでしょう。
一見うまくいきそうですね。

でも、まだ抜け穴があるんです。

割り込みが起こり、この処理が行われる前に、
もう一度、オーバーフロー/アンダーフローが、
起きている可能性があるのです。

TCNT2が、0xffffから、0x0000になったので、
OVI割り込みが発生したが、さまざまな理由で、
割り込み処理開始が遅れ、
その間にエンコーダーが逆転し、
TCNT2が、0x0000から、0xffffに
なってしまったらどうでしょう。

処理プログラムは、アンダーフローが起こったと判断し、
w = (--ext << 16) | t;
と処理します。
でも、本当はその前に、
w = (++ext << 16) | t;
を実行した後、
w = (--ext << 16) | t;
が実行されるべきなのですが、その遷移を見落とされ、
実際の値から2^16もの誤差を生じることになります。

この現象は、もはやソフトウエアーで処理できません。
そこで、TCNT2に、
オーバーフロー/アンダーフローが起きた回数を、
別のハードウエアーで勘定し、
処理しなければならないわけです。

具体的には、TCNT2が0x0000,0xffffを通過した回数を、
勘定し、--extか、++extのどちらを行うべきか判断するのに、
外部カウンターを使います。

それが先の解答の内容です。

さらに付け加えると、0x0000,0xffffを往復したのではなく、
本当に軸が、2^16カウント分回った可能性が理屈の上ではありますが、
それは、このシステムの処理限界を超えています。
ITUではなく、外部に高速のUp/Downカウンターをつけ、
処理しなければできません。

-- mac


スレッド概略
[3936(R)](起点)
 └[4001(U)]
   └[表示中]
     ├[4003(1)]
     └[4004(2)]


投稿順に移動
[←前の記事へ(P)]
[→次の記事へ(N)]


リスト表示へ
[このスレッド(T)]
[本記事の前後(L)]