CTCモードでのtimer3の設定-サーボライブラリとの競合


10

1秒あたり800回関数を呼び出すためにタイマーを設定したいと思います。私は1024のプリスケーラーでArduino MegaとTimer3を使用しています。プリスケーラーファクターを選択するには、次の手順を検討しました。

  • CPU周波数:16MHz
  • タイマー分解能:65536(16ビット)
  • ^ 6 / 16x10:選択されたプリスケーラによって分周CPUのFREQ 1024 = 15625
  • 残りを必要な周波数62500/800 = 19で割ります。
  • 結果+ 1をOCR3レジスタに格納します。

次の表を使用して、TCCR3Bのレジスタを設定しました。

ここに画像の説明を入力してください

エラー

コードをコンパイルすることは不可能です。これは、コンパイラによって返されるエラーです。

Servo \ Servo.cpp.o:関数 '__vector_32'内:C:\ Program Files(x86)\ Arduino \ libraries \ Servo / Servo.cpp:110:multiple definition of '__vector_32' AccelPart1_35.cpp.o:C:\プログラムファイル(x86)\ Arduino / AccelPart1_35.ino:457:最初にここで定義c:/ program files(x86)/ arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /。 ./../../../avr/bin/ld.exe:リラクゼーションを無効にする:複数の定義では機能しません

コード

volatile int cont = 0;
unsigned long aCont = 0;
void setup()
{
 [...]
  // initialize Timer3
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3A = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3A);
  // enable global interrupts:
  sei();
}

void loop()
{
 // Print every second the number of ISR invoked -> should be 100
 if ( millis() % 1000 == 0)
 {
   Serial.println();
   Serial.print(" tick: ");
   Serial.println(contatore);
   contatore = 0;
 }
}

[...]

// This is the 457-th line
ISR(TIMER3_COMPA_vect)
{
    accRoutine();
    contatore++;
}

void accRoutine()
{
  // reads analog values
}

サーボライブラリとの競合を解決するにはどうすればよいですか?

解決

次のコードを使用して競合を解決しました。コンパイルされますが、800Hzタイマーに関連付けられたカウンターはその値を増分しません。

volatile int cont = 0;

void setup()
{
  Serial.begin(9600);
  // Initialize Timer
  cli();          // disable global interrupts
  TCCR3A = 0;     // set entire TCCR3A register to 0
  TCCR3B = 0;     // same for TCCR3B

  // set compare match register to desired timer count: 800 Hz
  OCR3B = 20;
  // turn on CTC mode:
  TCCR3B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler:
  TCCR3B |= (1 << CS30) | (1 << CS32);
  // enable timer compare interrupt:
  TIMSK3 |= (1 << OCIE3B);
  // enable global interrupts:
  sei();

  Serial.println("Setup completed");
}

void loop()
{
  if (millis() % 1000 == 0)
  {
    Serial.print(" tick: ");
    Serial.println(cont);
    cont = 0;
  }
}

ISR(TIMER3_COMPB_vect)
{
  cont++;
}

主な問題が解決されたので、ここで、カウンターの増加の問題に関連する別の質問を作成しました。


プログラムでサーボライブラリを使用していますか?
jfpoilpret 2014

2
Servo.cppはISR(TIMER3_COMPA_vect)
TMa

1
代わりにTimer1、4、または5を使用してください。
Gerben、2014

1
サーボは、COMPAのメガでタイマー1、3、4、および5の割り込み関数を定義します。COMPBの使用についてはどうですか?
BrettAM 14

1
そうです。彼らはすべてのタイマーを独占しています。#define _useTimer3行を削除してライブラリを少し変更するか#undef _useTimer3、インクルードの直後に権利を置く必要があると思います。
Gerben、2014

回答:


4

残念ながら、Servuライブラリは、arduino megaにロードされると、タイマー1、3、4、および5の出力比較A(OCR * A)を予約します。それぞれに1つのISRしか設定できないため、ライブラリを変更せずにServoを使用している間は、独自のTIMER * _COMPA_vectを定義できません。

ただし、各ハードウェアタイマーは2つの出力コンペアレジスタを備えています。ServoはTIMER * _COMPB_vect割り込みを要求しないため、それらは自由に使用でき、まったく同じように動作します。

サーボライブラリのアクティビティに注意する必要があります。タイマーの設定が変更される可能性があります。デフォルトの順序はメガで、5、1、3、4であり、各12のサーボを提供します。必要な場合にのみタイマーを構成するので、25番目のサーボを追加するまで、タイマー3を使用して問題ありません。

コードを変更するには、OCR3A(出力比較レジスタ)の代わりにOCR3Bを使用し、TIMSK3(出力比較割り込みイネーブルビット)のOCIE3Aの代わりにビットOCIE3Bを設定します。次に、ISR関数を次のように変更します。 ISR(TIMER3_COMPB_vect){}

CTCモードはOCR3Aでのみ機能しますが、割り込み関数でTCNT3を0に設定すると、同様の動作が得られます。WGM12を使用してCTCモードをオンにする行を忘れずに削除してください。


わかりました!カウンターの増加に関するアドバイスはありますか?
UserK、2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.