ATtiny13Aでウォッチドッグタイマを使ったタイマー割り込み
一般的なタイマーとしても利用できます。
arduino環境で使うとシステム用に使われて利用出来ません。
タイマー割り込み、PWM出力、tone()なんかは使えません。
強引に使うことも可能ですが、その場合、一部の機能が使えなくなります。
delay()、micros()などのシステム稼働時間を使っている関数は機能しなくなります。
そこでウォッチドッグタイマを使って簡易的なタイマー割り込みを実現します。
テストとして、0.5秒周期でカウントをして10回目で割り込みを停止するプログラムを
作成してみました。取りあえず動作するようです。
ダウンロード test_tinyTimer.zip (1.4K)
#define BAUD_RATE 38400 #include <BasicSerial3.h> #include <avr/interrupt.h> //WDT利用のための定義 #define WDT_reset() __asm__ __volatile__ ("wdr") #define sleep() __asm__ __volatile__ ("sleep") #define WDT_16MS B000000 #define WDT_32MS B000001 #define WDT_64MS B000010 #define WDT_125MS B000011 #define WDT_250MS B000100 #define WDT_500MS B000101 #define WDT_1S B000110 #define WDT_2S B000111 #define WDT_4S B100000 #define WDT_8S B100001 // WDTタイマー開始 void WDT_start(uint8_t t) { cli(); // 全割り込み禁止 WDT_reset(); // ウォッチドッグタイマーリセット WDTCR |= _BV(WDCE)|_BV(WDTIE); // WDCE:ウォッチドッグ変更許可、WDTIE:動作種別=割り込み WDTCR |= t; // 割り込み間隔設定 sei(); // 全割り込み許可 } // WDTタイマー停止 void WDT_stop() { cli(); // 全割り込み停止 WDT_reset(); // ウォッチドッグタイマリセット MCUSR &= ~_BV(WDRF); // ウォッチドッグリセットフラグ解除 WDTCR |= _BV(WDCE)|_BV(WDE); // WDCEとEDEに1をセット WDTCR = 0; // ウォッチドッグ禁止 sei(); // 全割り込み許可 } uint16_t count =0; // タイマー割り込みで呼び出される関数 // 1〜10までカウントしたら停止する ISR(WDT_vect) { count++; serOutHex(count); serOut("\n\r"); if (count == 10) { WDT_stop(); serOut("STOP\n\r"); } } // シリアル出力整数を16進数で出力 void serOutHex(uint16_t h) { uint8_t c; for (int8_t i=12; i>=0; i-=4) { c = h>>i & 0xf; c = c >9 ? c+'A'-10: c+'0'; TxByte ((uint8_t)c); } } // シリアル出力 文字列出力 void serOut(const char* str) { while (*str) TxByte (*str++); } void setup() { WDT_stop(); // 起動直後に念のためにWDTを停止 serOut("START\n\r"); WDT_start(WDT_500MS); // ウォッチドッグタイマ 0.5秒間隔で割り込み実行 } void loop(){ sleep(); }
2014/11/30 追記
Arduino UNOの場合、WDTCRはWDTCSR、WDTIEはWDIEに変更する必要があります。
実行すると、こんな感じになります。
シリアル出力用ライブラリは「ATtiny13Aでシリアル通信(UART)を行う」で試した
basicserial3を使っています。スケッチのサイズは636バイトでした。
割り込みの停止、割り込みの再開、カウントにリセットも出来ました。十分使えます。
ウォッチドッグタイマを使うにあたっての問題点等
・ウォッチドッグタイマの利用はヒューズビットの設定が必要です。
ただし、arduino IDEのブートローダ書込み時に設定されるのでこの作業は不要です。
・最新のAVRマイコンの一部では、問題が発生するようです。
ブート直後の16ms後にウォッチドッグタイマによるリセットがかかる場合があり
ブート直後に明示的にタイマーを停止させる必要があるようです。
電子牛乳さんの「AVR がウォッチドッグタイマ発動後に再起動を繰り返す問題」の
記事で分かりやすく解説されています。
使った感じでは、ATtiny13Aでは発生しないみたいです(たぶん)。
該当デバイスにATtiny13はありますがATtiny13Aは無いですね。
他のデバイスでは注意が必要です。
« 秋月電子の「お楽しみ袋」を買ってみた | トップページ | Arduino Uno で006P(9V)電池を使って電源を確保する »
「arduino」カテゴリの記事
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Zorin OSでArduino Uno互換機(CH340)が認識しない(2025.01.19)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- Arduino用 SKK日本語変換ライブラリの開発 その1(2024.12.28)
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
「AVR」カテゴリの記事
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
- Arduino用SJIS漢字フォントライブラリ SDカード版を作成しました(2018.10.30)
- ATtiny13AでI2C接続キャラクタLCDを利用する(4)(2018.04.16)
- ATtiny13Aで赤外線リモコン受信センサーを使う(2)(2018.04.15)
- ATtiny13AでHC-SR04を使った距離計測(2018.04.14)
「ATtiny13A」カテゴリの記事
- ATtiny13AでI2C接続キャラクタLCDを利用する(4)(2018.04.16)
- ATtiny13Aで赤外線リモコン受信センサーを使う(2)(2018.04.15)
- ATtiny13AでHC-SR04を使った距離計測(2018.04.14)
- Arduino 1.8.5環境でATtiny13Aを利用する(2018.04.14)
- Arduino IDEを使ったATtiny13用スケッチの開発について(2016.08.30)
コメント
« 秋月電子の「お楽しみ袋」を買ってみた | トップページ | Arduino Uno で006P(9V)電池を使って電源を確保する »
はじめまして。
ATtiny13Aを使って同じようなリモコン受信器を製作しているのですがうまくいかず、
ネットで調べていたところ、こちらのブログにたどり着きました。
同じスケッチをArduinoで実行すると正常に動作するのですが、ATtiny13Aだとうま
くいきません。恐らくmicros( )関数が正しく機能していないではと推測しています。
Tinyマイコンでmicros( )関数を使う秘訣のようなものがありましたらご教授願えな
いでしょうか。
ちなみにFuseビットは、「9.6MHz 分周なし」に設定しています。
以上、よろしくお願いいたします。
投稿: マコ | 2015年6月 8日 (月) 10時34分
マコさん、はじめまして
私もATtiny13Aを使い込んでいるレベルではないのですが、分かる範囲で回答いたします。
>micros( )関数を使う秘訣
「TIMER0 を使わない」しか思いつかないです。
私はArduino IDE上でATtiny13Aを利用するための環境としてkosakalabさんのホームページ
「Arduino IDEでATtiny他の開発(Arduino-ISP編)」http://make.kosakalab.com/make/electronic-work/arduino-ide-arduinoisp/を利用しています。
この環境ではTIMER0を利用してdelay(),micros()を実装しています。
したがって、PWMやタイマー割り込み等でTIMER0を使うとdelay(),micros()が使えなくなります。
>同じスケッチをArduinoで実行すると正常に動作するのですが、ATtiny13Aだとうまくいきません。
私もArduino Unoで実装、テストしてATtiny13Aに移植しています。
この時、うまく動作しない場合があります。この時引っかかったのは次の場合です。
1)Fuseビットの設定を忘れた、クロックの設定が正しくない
=> delay(1000)で1秒が正確な時間かをチェック
2)ピンアサインが間違ている
ATtiny13AとArduino Unoでは利用できるピンが当然異なりますが、
私の場合、プログラムサイズを抑えるために直接レジスタを指定しています(PORTB)等。
ATtinyのPB4(D4ピン)は、Arduino Uno(ATmega328)ではD12(12ピン)となります。
投稿: たま吉さん(管理者) | 2015年6月 8日 (月) 21時36分
たま吉さん
早々のご返事ありがとうございます。
アドバイスを参考にもう少し調べてみます。
おやすみなさい。
投稿: マコ | 2015年6月 9日 (火) 00時35分
たま吉さん
やっと原因がわかりました。
micros( )関数内のインラインアセンブラで、割込み禁止/許可
の命令が漏れていました...お騒がせしました。
投稿: マコ | 2015年6月12日 (金) 00時52分
マコさん
ご報告ありがとうございます。
micros( )関数は自作なされたのですね。
投稿: たま吉さん(管理者) | 2015年6月12日 (金) 07時02分