macです。
土屋 さん<hideki-tsuchiya@xxxxxxxxxx> wrote:
> 上記のrefreshTCNT32()をTCNTが最大でも32767を超えない周期で呼ぶ。
> (ex.1mSインターバル割り込み等)
>
> 普段の参照はTCNT32値を使用すれば、
>
> >割り込みが起こり、この処理が行われる前に、
> >もう一度、オーバーフロー/アンダーフローが、
> >起きている可能性があるのです。
>
> の問題にも引っかかりません。
>
> ・・・と思うんですけどどうでしょう?
カウンタの場合、その瞬時の値がほしいことが多いので、
1msごとの値では、うまくない可能性がありますね。
1msの割り込み以外に、値が必要になったら、
このルーチンと等価の関数を、
臨時に実行すれば大丈夫かもしれません。
また、コメントアウトしているので問題ないですが、
割り込みルーチンの中で、割り込み許可/不許可をすると、
予期しない多重割り込みが起こり混乱したりします。
処理系依存ですが、割り込みルーチンは、
通常のサブルーチン同様に、
呼ぶことができないのが普通ですので、
volatile signed long TCNT32; // 32bits拡張カウンタ
volatile static unsigned short TCNTold; // 前回のTCNT値を記憶。
// 処理系依存の割り込み関数用の定義文
void refreshTCNT32(void)
{
unsigned short TCNTnew;
signed short diff;
TCNTnew = TCNT;
diff = TCNTnew - TCNTold; // 前回値と今回値の差を取得
TCNTold = TCNTnew;
TCNT32 += diff; // カウンタ値を更新
return;
}
// 通常の読み出しルーチン
signed long readTCNT32(void)
{
unsigned short TCNTnew;
signed short diff
disable_interrupt(); // 割り込み禁止
TCNTnew = TCNT;
diff = TCNTnew - TCNTold; // 前回値と今回値の差を取得
TCNTold = TCNTnew;
TCNT32 += diff; // カウンタ値を更新
enable_interrupt(); // 割り込み許可
return TCNT32;
}
というのが、この別解のまとめでしょうか。
他の方法としては、
GRA = 0x4000;
GRB = -0x4000;
のようにそれぞれ上限下限に設定し、
コンペアマッチが、交互に起これば一定方向に回り続けている。
片方だけが、連続して発生すれば、正転逆回転を繰り返している。
という判断を元に、オーバーフロー割り込みを使わず、
コンペアマッチを利用した方法も可能でしょう。
処理は多少複雑ですが、タイマーを使う方法に比べ、
Checkする周期を短くするとオーバーヘッドが増える。
周期を長くすると0x4000以上の変動を取りこぼす危険が出る。
という、問題を回避できる利点があります。
たまたま思いついた解法が、The Bestと思い込まずに、
時間が許すなら、考え付くもの全部をさらってやる、
という気構えでいくと、そのときには、使わなくても、
後で使えるネタが増え、効率的にスキルアップすると思います。
-- mac