ATMega328と内部発振器を使用していますか?


17

ATMega328Pに最適なプロジェクトがあると思います。しかし、私が見たすべての単純なプロジェクトでは、人々は常に16MHzの外部発振器を接続しています。私が見ることができるものから、それは8MHzの内部発振器を持っているはずです。私のプロジェクトは、多くの処理能力を必要とせず、タイミングも非常に正確である必要はありません(UARTおよびI2Cを除く)。プログラマーもいるので、ブートローダーについて心配する必要はありません。

外部発振器を使用する理由はありますか?

回答:


19

あなたが言っていないのは、この内部発振器の精度です。369ページのデータシートで見つけるのに時間がかかりました。

10%。10!キャリブレーションされたオシレーターの場合はどうですか?これはひどいです。これに対して1%の低いエラーを期待するのは不合理ではありません。Microchip / Atmelは、発振器を1%の精度で校正するためのドキュメントを提供しています

I2C同期プロトコルであり、最小および最大パルス時間が尊重される限り、タイミングの精度は関係ありません。一方、
UART非同期であるため、タイミングの正確性は確かに重要です。ほとんどのUARTでは、最後のビット(ストップビット)でハーフビットエラーが許可されるため、10ビットの送信では5%になります。

工場で調整された発振器はここでは動作しません。1%に到達するには、キャリブレーション手順を実行する必要があります。その場合、内部発振器を使用できます。それ以外の場合は、クリスタルを使用する必要があります。


1
ここで言っていることを補強させてください。時間と頭痛を省いて、クリスタルを手に入れましょう。電力が心配な場合は、32khz時計​​用クリスタル(48/88/168の場合は6PF ... 328についてはわかりません。移行シートを確認してください)を使用して、起動時に内部発振器を調整します。オシレーターのキャリブレーションルーチンは非常に細かいので、そのルートに行く場合は注意してください。別の回答の下にいくつかのサンプルコードを掲載しました。
bathMarm0t

6

UARTを使用しているため、水晶発振器を使用することをお勧めします。そうでない場合は、内部発振器を使用できます。一部のMCUには、UART動作に適した工場で調整された内部発振器があります。


2
UARTタイミングに関するこのアプリノートも参照してください:maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl

まあ、UARTは9600bpsにで動作しますが...私は、発振器とすべてのものを注文するが、それはそれなしで動作するかどう見て終わると思うことを、超簡単なシリアルディスプレイとの通信のためのものです
Earlz

3

「時間に敏感ではない」。UARTは非常に時間に敏感です。適切に同期されていない場合、完全なガベージが発生します。

オプション1:通常のクリスタルを使用します。クロック選択ヒューズを適切に変更します。クリスタルの選択は、どのボーを使用するか、この速度をどれだけ速くしたいかによって異なります。(完全に製造されている場合)標準レートに対して0%の誤差を与える「マジッククリスタル」があります。詳細については、セクション20 [USART0]の表を参照してください(データシートを読んでいます。

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

オプション2:電力が懸念される場合、32kHz水晶を使用して内部発振器を較正できます。32khzを使用すると、スリープモードでuA電流を取得できます(最大で2uAになりました)。ただし、タイマーを開始/停止し、timer2を非同期モードに切り替えることを含むキャリブレーションルーチンをセットアップする必要があります。

328Pコードは異なる場合があります...この関数は現在48/88で動作します(適切なF_CPU / baud定義を使用します。少しugい/完全にはリファクタリングされていませんが、 AVRFreaksフォーラムで「チューン32khzクリスタル」のようなものを検索してください。これは、あなたがこれからやっていくものの味です...必ずしも何がうまくいくとは限りません。

char OSCCAL_calibration(char starting_cal, int cal_value){
//Function calibrates the internal oscillator so usart comms go through.
//Works by continually checking two different timers:
//   (0 -> tied to internal, and 2 -> async to crystal).
//  Recommended cal_value = 5900 for the crystals we're using.
//  Must be running 8MHZ with clkdiv8 fuse enabled.
//  TODO: Make sure to check all the math on this later.
unsigned char calibrate = FALSE;
int temp;
unsigned char tempL;
volatile char osccal_temp=starting_cal;
int cal_bandwidth = 50;

//int cal_value = 6250;
//int cal_value = 5900; //Works.  Need to find out why.

//Dont use clock prescalers.  We're already div8ing.
//CLKPR = (1<<CLKPCE);        // set Clock Prescaler Change Enable
// set prescaler = 8, Inter RC 8Mhz / 8 = 1Mhz
//CLKPR = (1<<CLKPS1) | (1<<CLKPS0);

TIMSK2 = 0;             //disable OCIE2A and TOIE2
ASSR = (1<<AS2);        //select asynchronous operation of timer2 (32,768kHz)

OCR2B = 200;            // set timer2 compare value.  We probably only need to compare A
OCR2A = 200;

TIMSK0 = 0;             // delete any interrupt sources

TCCR2A = (1<<WGM21);    //Normal operation.  Reset timer on hitting TOP (ocr2a).
TCCR2B = (1<<CS20);     // start timer2 with no prescaling

TCCR1B = (1<<CS10);     // start timer1 with no prescaling

//wait for everythnig to mellow out.
while((ASSR & (1<<TCN2UB)) | (ASSR & (1<<OCR2BUB)) | (ASSR & (1<<TCR2BUB)) | (ASSR & (1<<OCR2AUB)) | (ASSR & (TCR2AUB)));       //wait for TCN2UB and TCR2UB to be cleared

//This is specifically for the crystal to stabilize.  Check for better times.
_delay_ms(1000);

while(!calibrate){
    cli();  // disable global interrupt

    TIFR1 = 0xFF;   // delete TIFR1 flags
    TIFR2 = 0xFF;   // delete TIFR2 flags

    TCNT1H = 0;     // clear timer1 counter
    TCNT1L = 0;
    TCNT2 = 0;      // clear timer2 counter

    //Stop timer on compare match.
    while ( !(TIFR2 & (1<<OCF2A)) );
    TCCR1B = 0;

    //Check for overflows (useless if it happens).
    sei();
    if ( (TIFR1 & (1<<TOV1)) ){
        temp = 0xFFFF;      // if timer1 overflows, set the temp to 0xFFFF
    }else{   // read out the timer1 counter value
        tempL = TCNT1L;
        temp = TCNT1H;
        temp = (temp << 8);
        temp += tempL;
        }

    //Check timer value against calculated value.           
    if (temp > (cal_value+(cal_bandwidth/2))){
        //Oscillator is too fast.
        osccal_temp--;
        OSCCAL=osccal_temp;
    }else if (temp < (cal_value-(cal_bandwidth/2))){
        //Oscillator is too slow.
        osccal_temp++;
        OSCCAL=osccal_temp;
    }else{
        //Just right.
        calibrate = TRUE;
        }

    TCCR1B = (1<<CS10); // start timer1
    }

//TODO: Stop timers, ya?
//Now setup timer2 to run "normally" aka async+interrupts.
//Disable interrupt source. Set mask.  Wait for registers to clear.
TIFR2 = (1<<TOV2);
TIMSK2 = (1<<TOIE2);
ASSR = (1<<AS2);        //select asynchronous operation of timer2 (32,768kHz)
TIMSK0 = 0;             // delete any interrupt sources

//Normal Op. 256 prescale.
TCCR2A = 0x00;
TCCR2B = (1<<CS22) | (1<<CS21);

TCCR1B = 0x00;     // turn off timer1

//wait for everythnig to mellow out.
while((ASSR & (1<<TCN2UB)) | (ASSR & (1<<OCR2BUB)) | (ASSR & (1<<TCR2BUB)) | (ASSR & (1<<OCR2AUB)) | (ASSR & (TCR2AUB)));       //wait for TCN2UB and TCR2UB to be cleared

//This is specifically for the crystal to stabilize.  Check for better times.
_delay_ms(1000);
return osccal_temp;
}

2

また、水晶の起動には時間がかかることに注意してください。それは実際にはその精度のためです:それは非常に狭い周波数帯域からのみエネルギーを取ります。これは、時々非常に短い時間mcuを起動するバッテリー駆動のものにとっては負担になる可能性があります。クリスタルが起動するために最大電力でmsを待つことは、純損失です。セラミック共振子は、内部RC発振器よりも正確ですが、水晶振動子よりも小さく、それに応じて起動します。

もちろん、16MHzのatmegaはより多くのジュースを飲み、8MHzのものよりも高い電圧を必要としますが、8MHz(またはそれ以下、32kHzまで)の水晶が利用可能です。この単なる選択はエネルギー節約にもなります。


0

あまり正確なタイミングが必要ない場合は、外部発振器は必要ありません。いくつかの古いプリンターを分解していると、たまたま多くのICが見えますが、ボード上の単一の発振器は見えません。


0

私はあなたがすでにこのアプリノートを見たことがあると思います: AVR053:内部RC発振器の較正

私はそれから推測し、上記の@drxzclのコメントからのアプリノートから、理論的に何が正しいかを判断できるはずです。


受け入れ答えがすでにある場合は、あなたがそうでなければ、それは非常に有用ではないですが、より多くの何かを言うようにしてください
clabacchio

@clabacchio-この回答は2日前のもので、受理された日付は昨日からです。これが投稿されたとき、それは受け入れられなかったはずです。
-stevenvh

@stevenvh正しい、私はそれが単なる編集だとは知りませんでした。しかし、それは不完全な答えです
clabacchio

@clabacchio-「不完全な答え」。同意した!「決めることができるはず」が非常に役立つとは思えません。
-stevenvh

@clabacchio-ねえ、私も「2日前」と言っています。少し前に、「昨日答えました」と言われました。ちょうど48時間だったに違いありません!:-)
stevenvh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.