Arduinoのタイマー OCRレジスタは「n」じゃなく「n - 1」の値を設定せよ
ミスが広まる 1/1023 vs 1/1024は、Arduino-UNO(ATmega328pマイコン)
のA/Dコンバータ・スケーリングのお話しでしたが、今回はタイマーのコンペアマッチ
レジスタのお話しです。
Arduinoのタイマーを直接操作する時(例えばMsTimer2などのタイマー
ライブラリーを使わずにタイマー割り込みを使いたい時など)、CTCモードで
アウトプットコンペアレジスタにタイマーの最大カウント値を設定します。
※Arduinoから「タイマー0」を取り上げる(ユーザーが使う) では
「1m秒」割り込みを例にしました。
1msつまり1kHzの割り込み周期を得るには、
・CTCモードに。 (コンペアマッチでカウンタゼロクリアー)
・16MHzのクロックをプリスケーラーで1/64して250kHzに。
・それを1/250して1kHzに。
この1/250するのがアウトプットコンペアレジスタへの設定です。
↑の例では
OCR0A = 250 - 1; // 250カウントで1kHzを
の所。
1/250なんで「250 - 1」を設定しています。
これをミスして「-1していない」プログラム例や解説を見かけるのです。
なぜ「n - 1」なのかは、このタイミング図を見れば分かるかと。
TOP値がOCR:コンペアレジスタへの設定値。
そして、CTCモードだとBOTTOM値はゼロになります。
TOP値を検出した次のサイクルがゼロとなるわけです。
例えば「1/4」したい時、TOP値つまりコンペアレジスタの値を
「4」にしてしまうと・・・
「0 1 2 3 4 0 1 2 3 4 0・・・」と繰り返しが「5」になってしまいます。
TOP値としてOCRに設定するのは「カウント周期 - 1」でなければいけません。
「-1」しないと、「1/4」が欲しいのに「1/5」になってしまうという
スカタンが発生します。
これに気付かない原因の推測ですが、
・とりあえず、それらしい動きをしてるから。
・16ビットタイマーであるタイマー1に対して、大きな値をセットしてる。
そのままの値と-1した場合とで、タイマー周期にほとんど違いが出ない
から気がつかない。
・8ビットタイマーでも、ミスを測定する手段を持ってない、あるいは
積極的に結果を計ろうとしていない。
※周波数カウンタやオシロスコープなどの測定器をつなぎ
テストパルスを出せばすぐに気がつくはず。
・ハードウェアの非同期カウンタを思い浮かべている。
※1/10カウンタなら、7→8→9→[10=0]→1→2→
と、10検出で直ちにリセットされて0になるので。
こんなところかと。
※見かけたミスの例
・ArduinoのTimerを初心者が1からなんとなくわかるためのメモ - Qiita
16MHzクロックを1/256し、「OCR1A = 62500;」として「1秒」としている。
・Arduinoでtimerを使った割込み処理の方法 ? 自作のいろいろ
「OCR2A=100; //100カウントごと(50μs)毎」と。。。
・Timer1 - FreeStyleWiki
ちょっと違う。
・タイマー割り込みを使う - arduino始めました
惜しいような。。。
・Timer0 & 1
アセンブラでもミス。
多くの正しい解説もありますが、ミスしたのが目立っちゃいます。
そして、もうひとつ気になるのが割り込み処理内で走らせるプログラム。
「呼んですぐに戻ってくる関数」が基本。
そして、それがメインの処理とぶつからないこと。
他の割り込み処理に影響(長い時間待たせる)を与えてもダメ。
割り込みの中で「Serial.println(xxx)」を使ってる例を見かけるのですが、
これはいかがなものかと・・・。
| 固定リンク
「Arduino」カテゴリの記事
- パルスジェネレータをI2C液晶で動かす(2025.01.28)
- EEPROMを使ったシリアル受信バッファ 512kバイトに増設(2024.12.26)
- 1/nカウント方式とDDS方式の2相パルス発生回路(2024.10.13)
- おっと。map関数の計算桁に注意(2024.10.06)
- DDS方式の2相パルス発生回路、周波数スキャン機能を付ける(2024.10.05)
「割り込み処理」カテゴリの記事
- 1クロックでも速くしたい 割込を「ISR_NAKED」で(2024.09.30)
- 1クロックでも速くしたい DDS方式の2相パルス発生器(2024.09.27)
- 最適化処理のせいで悩んだぞ 呪文volatile再び(2024.06.06)
- I2C液晶のアクセス、割り込みで処理しないようにすると(2024.04.12)
- I2C液晶のアクセス、割り込み処理で遅れる原因らしきもの(2024.04.07)
コメント
注目されてます。
PIC AVR 工作室 ブログ:あぁ、タイマーの設定値、-1するの忘れがちなんだ
よなぁ。
https://brown.ap.teacup.com/nekosan0/4150.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年2月 9日 (日) 21時57分
オーバーフロー割り込みでのお話。
http://igarage.cocolog-nifty.com/blog/2021/12/post-4a81b7.html
Arduinoで使われているATmega328P、8bitタイマーでオーバーフロー割り込みが発生するのは「255の次のクロック」。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年12月25日 (土) 10時24分