Arduinoでタイマー割り込みを作成するにはどうすればよいですか?


9

Arduinoで時間遅延割り込みを作成しようとしています。これは内部割り込みなので、interrupts()関数を使用したいと思います。

例:割り込みのタイミングのみでライトを点滅させたいとしましょう。

サンプルコードがありますが、外部割り込み(attachInterrupt())を使用しています。内部割り込みを使い続けたいのですが。


2
Kortukが示した点は、attachInterruptは抽象的なものであり、外部コンポーネントを接続していないということだと思います:)
clabacchio

この記事はあなたを助けるかもしれません。engblaze.com/...
セス・アーチャー・ブラウン

回答:


10

Noah Stahlのブログには、Timer2でLEDを点滅させる例があります。それとデータシートを使用して、使用したい割り込み(つまり、通常の機能を放棄する余裕がある、または変更したい割り込み)にそれを適合させることができるはずです。Timer2は通常、一部のPWM機能に使用されます。

彼の例はATmega2560を引用しています。ATmega328pでも動作することを確認できました。より有用なArduino割り込みの例については、彼のサイトを見てください。

編集:

これは、わずかに編集された(主にコメントの)バージョンのNoahのコードです。関連するデータ構造またはハードウェアを初期化した後、Arduinoのsetup()関数からTimer2init()を呼び出します。これを行うと、タイミングと割り込みが開始されるためです。

F / ex、3桁の7セグメントディスプレイを多重化するために使用したので、タイマーを初期化する前に、ディスプレイI / Oレジスタを初期化し、ISRが検索する場所のディスプレイデータをブランクにしました。

データシートのいくつかの有用なタイミングデータと、別のタイミングスキームを設定するための参照用の独自の計算のコメントに表があります。

ISR()マクロは、通常の関数の入り口と出口の代わりにISRの割り込み入り口コードと出口コードを作成し、それを適切な割り込みベクトルにリンクします。その関数の残りの部分は、1)各割り込みで実行されるコード、および2)次の割り込みのタイマーをリセットするコードコードです。

書かれているように、これは.pdeまたは.inoスケッチ(またはeclipse、f / exを使用する場合は.cppファイル)にドロップする必要があります。スケッチはLEDPINを#defineする必要があり、setup()はTimer2init()を呼び出す必要があります。ループ関数は空かそうでないかもしれません。ダウンロード時にLEDが点滅し始めます(まあ、文字通り、Timer2init()が呼び出された後)。

/*
 * From sample interrupt code published by Noah Stahl on his blog, at:
 * http://arduinomega.blogspot.com/p/arduino-code.html
 * 
 */


/*** FUNC

Name:           Timer2init

Function:       Init timer 2 to interrupt periodically. Call this from 
                the Arduino setup() function.

Description:    The pre-scaler and the timer count divide the timer-counter
                clock frequency to give a timer overflow interrupt rate:

                Interrupt rate =  16MHz / (prescaler * (255 - TCNT2))

        TCCR2B[b2:0]   Prescaler    Freq [KHz], Period [usec] after prescale
          0x0            (TC stopped)     0         0
          0x1                1        16000.        0.0625
          0x2                8         2000.        0.500
          0x3               32          500.        2.000
          0x4               64          250.        4.000
          0x5              128          125.        8.000
          0x6              256           62.5      16.000
          0x7             1024           15.625    64.000


Parameters: void

Returns:    void

FUNC ***/

void Timer2init() {

    // Setup Timer2 overflow to fire every 8ms (125Hz)
    //   period [sec] = (1 / f_clock [sec]) * prescale * (255-count)
    //                  (1/16000000)  * 1024 * (255-130) = .008 sec


    TCCR2B = 0x00;        // Disable Timer2 while we set it up

    TCNT2  = 130;         // Reset Timer Count  (255-130) = execute ev 125-th T/C clock
    TIFR2  = 0x00;        // Timer2 INT Flag Reg: Clear Timer Overflow Flag
    TIMSK2 = 0x01;        // Timer2 INT Reg: Timer2 Overflow Interrupt Enable
    TCCR2A = 0x00;        // Timer2 Control Reg A: Wave Gen Mode normal
    TCCR2B = 0x07;        // Timer2 Control Reg B: Timer Prescaler set to 1024
}



/*** FUNC

Name:       Timer2 ISR

Function:   Handles the Timer2-overflow interrupt

Description:    Maintains the 7-segment display

Parameters: void

Returns:    void

FUNC ***/

ISR(TIMER2_OVF_vect) {
    static unsigned int led_state = 0; // LED state

    led_state = !led_state;         // toggles the LED state
    digitalWrite(TOGGLE_PIN, led_state);

    TCNT2 = 130;     // reset timer ct to 130 out of 255
    TIFR2 = 0x00;    // timer2 int flag reg: clear timer overflow flag
};

(@Kortuk:あなたが参照するコメントは、ここでのいくつかのコメンテーターの私の観察であり、あなたを個人的に対象としたものではなく、不必要でした。お詫びし、私はそれを削除しました。)私はあなたが提案したように私の回答を拡大しました。今では、実証的であるだけでなく、教育的でもあります。これには、自分が使用するためにコードに書き込んだコメント(つまり、6か月後にそれらを理解できれば、他の誰かもできるようになります)と、いくつかの「使用方法」の説明が含まれています回答。あなたの提案をありがとう。
JRobert

timer0とtimer1(少なくともatmega328)では、32と128のプリスケールは使用できないことに注意してください。
tuupola

知っておくと便利です。ありがとうございます。私はこれを(これまでのところ)Timer2に使用しており、基本的にはドロップインです。
JRobert、2012

5

attachInterrupt()関数は、実際にピンの外部状態変化への割り込みを装着され、それは他のオプションを持っていません。

上の同じページモードオプションは、次のように記載されています:

モードは、割り込みをトリガーするタイミングを定義します。4つの定数が有効な値として事前定義されています。

  • ピンがローのときはいつでも割り込みをトリガーするLOW
  • ピンが値を変更するたびに割り込みをトリガーするCHANGE
  • RISINGは、ピンがローからハイになったときにトリガーします。
  • ピンがハイからローになるときのフォールリング

悪い知らせの持ち主になって申し訳ありません。それも私が最初に探したものの1つです。


私は、彼は彼ではなく、外部機器の内部タイマを、使用したいということだと思います...しかし、それが可能だ場合、私は言うことができないので、私は、非常によくArduinoのを知っていない
clabacchio

@clabacchio、私は唯一のオプションは外部トリガーを使用することであると言っています。内部タイマー機能はありません。
Kortuk、2012

ああ、いいね:)でも、少なくともArduinoボードにはタイマーがありますか?
クラバッキオ

はい、それは彼らが遅延のようなことを達成する方法です。
Kortuk

1
@ icarus74 ATMega328には実際には3つのタイマー(1つは16b、2つは8b)がありますが、それらはすべてArduinoによって使用されます。1つはdelay()やmillis()のような関数に使用され、3つはすべてPWMに使用されます(詳細はArduino IDEの関数 'init()'、ファイル 'wiring.c'にあります)。
vasco

2

PWMに関するこの記事では、Arduinoタイマーの使用に関する多くの疑問を解決します。Arduinoには2つの8ビットタイマーと1つの16ビットタイマーがあります。ISR関数をタイマーに直接フックする高レベルのAPIはありません。これは、Arduino SDKに同梱されて(つまり、標準ライブラリとして)提供されていますが、Special-Function-Registersおよびbit-arithmetic /を設定するやや低レベルのメソッドです。それらの操作。ただし、Timer oneというユーザー提供のライブラリがあります。


どのArduinoが参照されているかに応じて、実際にはいくつかの異なるタイマーの組み合わせが可能です。答えは誤解を招くものです。
2013

@SeeminglySo、詳しく説明しますか?Arduinoハードウェアについて話している場合、答えは質問のコンテキスト内であり、質問が尋ねられる時間でもあることに注意してください。
icarus74 2013年

Arduino Mega(ATmega1280ベース)は2009年3月26日にリリースされ、Mega 2560(ATmega2560)は2010年9月24日にリリースされました。どちらもこの質問がされる前のことです。両方のマイクロコントローラーには、回答で指定された2x 8ビットおよび1x 16ビットタイマー/カウンターよりも多くのものが含まれています。
2013

私がこれまでに見たほとんどの相互作用は、Arduinoへの明確な参照を持ち、DuemilanoveまたはUnoのようなもの、つまり328シリーズベースのボードを意味します。その他のボードは、uPシリーズ番号によって常に明示的に認定されています。またはメガ、ナノ、マイクロなど。とにかく、私は謙虚に修正を受け入れます。この文脈では、明確化の方が優れています。
icarus74 2013年

1

ArduinoはATMega328で3つのタイマーをすべて使用しています。Timer1(16ビット)のような機能のために使用されるdelay()millis()ピン5と6他の二つのタイマーのPWM出力のために- Timer0Timer2ピン3、9、10、11にPWM出力のために使用されます。

そのため、タイマー割り込みのためのArduino関数はありません。しかし、方法があります。このコードを使用して、タイマー割り込みを有効にすることができますTimer2

ISR(TIMER2_OVF_vect) {
  // Interrupt routine.
}

void setup() {
  // Enable Timer2 interrupt.
  TIMSK2 = (0<<OCIE2A) | (1<<TOIE2);
}

void loop() {
  // Your main loop.
}

このコードはテストせずに作成したので、間違えた可能性があります。その場合は、データシートp.156をご確認ください。

タイマ周波数(プリスケーラ)を変更したい場合は、レジスタを変更するだけTCCR2Aです。詳細については、データシートの153ページを参照してください。ただし、タイマーの周波数を変更すると、2つの出力ピンのPWM信号の周波数も変更されます。


ATmega328での私の知る限りTimer0Timer28ビットであり、唯一のTimer116ビットです。
tuupola

いいえ、これは正しくありません。delay()とmillis()、およびピン5と6のPWM出力に使用されるのは、Timer1ではなくTimer0です。Timer0は8ビットタイマーです。たとえば、Arduinoタイマーと割り込みを参照してください。
Peter Mortensen、2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.