ATmega328でのAVRタイマーの高速化


9

ATmega328でクロックプリスケーラー64で実行すると、不明な理由により、実行中の特定の時間に私のタイマーの1つがスピードアップします。

ATmega328で2つのタイマーを使用して、TLC5940が必要とするクロッキングを生成しています(理由については以下を参照してください。これは質問には重要ではありません)。TIMER0Fast PWM onを使用してクロック信号を生成し、OC0B次のように設定されます。

TCCR0A = 0
    |(0<<COM0A1)    // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
    |(0<<COM0A0)    // 
    |(1<<COM0B1)    // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
    |(0<<COM0B0)
    |(1<<WGM01)     // Bits 1:0 – WGM01:0: Waveform Generation Mode
    |(1<<WGM00)
    ;
TCCR0B = 0
    |(0<<FOC0A)     // Force Output Compare A
    |(0<<FOC0B)     // Force Output Compare B
    |(1<<WGM02)     // Bit 3 – WGM02: Waveform Generation Mode
    |(0<<CS02)      // Bits 2:0 – CS02:0: Clock Select
    |(1<<CS01)
    |(0<<CS00)      // 010 = clock/8
    ;
OCR0A = 8;
OCR0B = 4;
TIMSK0 = 0;

TIMER2データラインをいじって、256 TIMER0サイクルごとにブランキングパルスを生成し、次のように設定されます。

ASSR = 0;
TCCR2A = 0
    |(0<<COM2A1)    // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
    |(0<<COM2A0)    // 
    |(0<<COM2B1)    // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
    |(0<<COM2B0)
    |(0<<WGM21)     // Bits 1:0 – WGM01:0: Waveform Generation Mode
    |(0<<WGM20)
    ;
TCCR2B = 0
    |(0<<FOC2A)     // Force Output Compare A
    |(0<<FOC2B)     // Force Output Compare B
    |(0<<WGM22)     // Bit 3 – WGM02: Waveform Generation Mode
    |(1<<CS22)      // Bits 2:0 – CS02:0: Clock Select
    |(0<<CS21)
    |(0<<CS20)      // 100 = 64
    ;
OCR2A = 255;
OCR2B = 255;
TIMSK2 = 0
    |(1<<TOIE2);    // Timer/Counter0 Overflow Interrupt Enable

TIMER2オーバーフロー時にISRを呼び出します(256サイクルごと)。ISRは手動でブランキングパルスを生成し、必要に応じてラッチパルスを生成します。

volatile uint8_t fLatch;

ISR(TIMER2_OVF_vect) {
    if (fLatch) {
        fLatch = 0;
        TLC5940_XLAT_PORT |=  (1<<TLC5940_XLAT_BIT);        // XLAT -> high
        for (int i=0;i<10;i++)
            nop();
        TLC5940_XLAT_PORT &= ~(1<<TLC5940_XLAT_BIT);        // XLAT -> high
    }
    // Blank
    TLC5940_BLANK_PORT |= (1<<TLC5940_BLANK_BIT);
    for (int i=0;i<10;i++)
        nop();
    TLC5940_BLANK_PORT &= ~(1<<TLC5940_BLANK_BIT);
}

nop()上記のコードの遅延は、ロジックアナライザのトレースでパルスをより明確にするためのものです。main()関数のループは次のようになります。シリアルデータを送信し、ISRがラッチを処理するのを待ってから、もう一度やり直します。

for (;;) {
    if (!fLatch) {
        sendSerial();
        fLatch = 1;
        _delay_ms(1);
    }
    nop();
}

sendSerial()いくつかのSPI送信を行います(簡潔にするために、ペーストビンのコード)。私の問題は、sendSerial()完了後、fLatch低(処理済み)に設定されるのを待っている間、クロッキングタイマーがスピードアップすることです。ロジックアナライザーのトレースは次のとおりです(同じ信号がグラフィックを小さくし続けている領域を切り取っています)。

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

左側のチャネル0と1は、送信されるSPIデータの末尾を示しています。また、左側のチャネル4には、ブランキングパルスが表示されます。チャネル2では、クロッキングパルスが期待どおりに変化します。画像内のギャップのすぐ近くが、ルーチン内にfLatch設定さ1れてmain()います。そして、その後すぐにTIMER0約4倍にスピードアップします。最終的に、ブランキングパルスとラッチパルスが実行され(チャネル3および4、画像の右3分の1)、クロックパルスが通常の周波数に戻り、シリアルデータが再び送った。でdelay_ms(1);線を抜いてみましたmain()が、同じ結果が得られます。どうしたの?ATmegaは20Mhzクリスタルからクロックされ、次のコードを使用して64倍スローダウンすることに注意してください:

CLKPR = 1<<CLKPCE;
CLKPR = (0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(0<<CLKPS0);

用途:TLC5940 LEDドライバーの制御を実験しています。これらのチップには、外部クロックに加えて、クロッキングサイクルの最後にリセットが必要です。


デバッガーがある場合は、タイマーが速すぎるときにコードを停止し、そのタイマーの構成レジスターを読み戻してください。誤った値を持つものが見つかったら、このレジスターの変更でブレークポイントをトリガーし、コードのどの部分が正しく実行されていないかを確認します。問題はあなたが使用する可能性のある外部ライブラリにあり、遅延などの内部的なもののためにそのタイマーを使用していると思います。
Blup1980 2013

2つの問題:a)JTAGプログラマーがいないため、チップをデバッグする方法がないb)上記のセットアップ後にタイマーレジスターの値を変更しないので、タイマーレジスターの値が実際に変わります。それは素朴ですか?
angelatlarge 2013

1
実際に使用する1つのライブラリがUART設定を変更する可能性があります。sendSerial()関数を使用しているようです。それはあなたのコードの一部ですか、それとも外部ライブラリですか?設定を変更するのはあなたではなく、呼び出されたライブラリ内のコードの一部です。シリアルポートを使用して構成パラメーターを出力し、何が変更されたかを理解することをお勧めします。また、使用されているライブラリ(ある場合)のソースを確認し、それらがそのタイマーを使用していないことを確認することもできます。
Blup1980 2013

1
@ Blup1980が示唆したこととは別に、試してみる価値があると思われるもう1つのことは、TLC5940を削除して、クロックラインで奇妙な動作を行わないようにすることです。
PeterJ 2013

@ Blup1980 UARTの関連性がわかりません。USARTfor SPIを使用しておらず、「通常の」SPI機能のみを使用しています。sendSerial()SPIを介してデータを送信する私のコードですTCCR。(タイマー制御)レジスターには触れません。
angelatlarge 2013

回答:


1

迅速なデバッグのために、TLC5940のArduinoライブラリを使用して同じことを実行し、高速になるかどうかを確認します。ライブラリで動作する場合は、そのソースを確認して自分のものと比較できます。AVRに慣れているので、ArduinoソースをネイティブAVRに簡単に変換する必要があります。

コンパイルしたArduinoスケッチをAVRにアップロードする方法がわからない場合に備えて:スケッチをコンパイルすると、hexファイルが作成されます(設定で詳細モードをオンにすると、ファイルの正確な場所を確認できます)。お気に入りのプログラマーを使用して、そのヘックスをAVRにアップロードできます。

それが役に立てば幸い

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.