2

を再生する別の出力に関連する反転出力をピンに持たせようとしていますがtone()、35us @8MHz または 158us @1MHz クロックの遅延があります。遅延はクロック周波数に反比例しないため、固定の 16us +142 クロック サイクルの遅延があるようです。彼らは非常に長いです!なんで?

これはコードです:

/* Per ATTINY85:
1: I/O5 PB5 A0 RS 
2: I/O3 PB3 A3          - Geiger inverted earphone out
3: I/O4 PB4 A2          - Geiger earphone out
4: GND
5: I/O0 PB0    MOSI SDA - Battery test/Geiger LED out
6: I/O1 PB1    MISO     
7: I/O2 PB2 A1 SCLK SCL INT0 - Geiger probe in (via NPN transistor)
8: Vcc
*/

#include<avr/sleep.h>

byte state;
volatile byte P;
int B;
int Bo;
byte LED=0;
unsigned long t=0;

void particella() 
{
    P=1;
}

ISR(PCINT0_vect)
{
    if (!(PINB & (1<<PB4)))
        PORTB |= (1<<PB3);
    else 
        PORTB &= ~(1<<PB3);
}

void setup()
{
    pinMode(0, OUTPUT); // Al LED.
    pinMode(2, INPUT); // Dal transistor dal tubo Geiger.
    pinMode(2, INPUT_PULLUP); // Pull-up per il collettore del transistor.
    pinMode(4, OUTPUT); // All'auricolare.
    pinMode(3, OUTPUT); // All'auricolare (copia invertita del 4).

    GIMSK = 0x60;    // turns on external and pin change interrupts.
    PCMSK = 0x10;    // turn on interrupts on pin PB4.
    sei();           // set interrupts (enable).

    tone(4,2000,100); // Power on beep
    PORTB|=0b00000001;
    delay(700);
    PORTB&=0b11111110;
    delay(1000);
    readVcc();

    for(byte n=1; n<=state; n++)
    {
        PORTB|=0b00000001; // Accende il LED su I/O0 = PB0
        tone(4,2000,25); // Bip acuto a ogni lampo.
        delay(30);
        PORTB&=0b11111110; //  Spegne il LED su I/O0 = PB0
        delay(250);
    }
    delay(350);

    attachInterrupt(0, particella, FALLING);
}


void loop()
{
    if(P)
    {
        P=0;
        t=millis();
        PORTB|=0b00000001; // Accende il LED su I/O0 = PB0
        LED=1;
        tone(4,1000,5); // Fa TIC nell'auricolare.
    }

    if(millis()-t>=10 && LED==1) 
    {
        LED=0; PORTB&=0b11111110; //  I/O0 = PB0 LED OFF after 10ms.
    }
}
4

1 に答える 1

1

ISR のコードが実行されるまでには、多くの遅延があります。

まず、ハードウェアの遅延です。これらはデータシートに記載されており、入力が変化したことを認識してラッチし、現在の命令を終了し、命令ポインターをスタックにプッシュし、ISR へのジャンプを実行する時間が含まれます。 ここに画像の説明を入力 ここに画像の説明を入力

次に、ソフトウェアの遅延です。最初に割り込みベクトルから IST アドレスへのジャンプがあり、次にコンパイラは一連の命令を ISR の先頭に配置して、すべてのレジスタが保存され、正しい期待値を持つようにします。これを「プリアンブル」と呼びます。

https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

ハードウェアの遅延についてできることはあまりありませんが、ソフトウェアの遅延を大幅に減らすことができます。特に、あなたのような非常に単純な ISR の場合はそうです。1 つの方法は、変更したレジスタのみを保存する「裸の」ISR を作成することです。上記のコードでは、レジスタを 1 つ変更するだけで取得できる可能性があります。

PINレジスタに書き込んでビットを反転させるというトリックを使用して、データレジスタを使用せずにISR機能を実行することも可能だと思います。 ここに画像の説明を入力

グーグルでこれらすべての詳細情報を見つけることができるはずです。または、これらのポイントのいずれかに関する特定のガイダンスが必要な場合は、ここに戻って報告してください!

別のアプローチ - 組み込みのハードウェア反転出力を使用する

dead timeこのチップの Timer1 には、探している反転信号を自動的に出力する組み込みの反転出力があり、反転出力と非反転出力の間の遅延は 1 サイクルよりはるかに少なくなります (意図的にトランジション)。

ここに画像の説明を入力

これには、タイマー レジスタをプログラミングして反転出力を有効にする必要があり、反転出力は特定のピンでのみ使用できますが、通常は問題ありません。

于 2018-09-18T15:42:21.937 に答える