Menggunakan ATMega328 dengan osilator internal?

18

Saya punya proyek yang menurut saya paling cocok untuk ATMega328P. Namun, dalam setiap proyek sederhana yang saya lihat, orang selalu memasang osilator eksternal 16MHz. Dari apa yang saya lihat, seharusnya memiliki osilator internal 8MHz. Proyek saya tidak memerlukan banyak kekuatan pemrosesan, juga tidak perlu waktu yang sangat tepat (selain untuk UART dan I2C). Saya punya programmer juga, jadi saya tidak perlu khawatir tentang bootloader.

Apakah ada alasan bagi saya untuk menggunakan osilator eksternal?

Earlz
sumber

Jawaban:

20

Yang tidak Anda katakan adalah keakuratan osilator internal ini. Butuh beberapa waktu untuk menemukannya di lembar data , di halaman 369.

10%. Sepuluh persen! Dan itu untuk osilator yang dikalibrasi? Ini mengerikan. Tidak masuk akal untuk mengharapkan kesalahan serendah 1% untuk ini . Microchip / Atmel menyediakan dokumen untuk mengkalibrasi sendiri osilator hingga akurasi 1%.

I2C adalah protokol yang sinkron , dan ketepatan waktu tidak relevan selama waktu pulsa minimum dan maksimum dihormati.
UART di sisi lain tidak sinkron , dan kemudian ketepatan waktu memang penting. Kebanyakan UART memungkinkan kesalahan setengah bit di bit terakhir (bit stop), jadi itu 5% untuk transmisi 10 bit.

Osilator dikalibrasi pabrik tidak akan melakukannya di sini. Anda harus melalui prosedur kalibrasi untuk mendapatkan 1%. Dalam hal ini Anda dapat menggunakan osilator internal. Jika tidak, Anda harus menggunakan kristal.

stevenvh
sumber
1
Biarkan saya memperkuat apa yang dikatakan di sini. Hemat waktu dan sakit kepala Anda dan dapatkan kristal. Jika daya mengkhawatirkan, gunakan kristal arloji 32khz (6PF untuk 48/88/168 ... tidak yakin tentang 328. periksa lembar migrasi) untuk menyetel osilator internal saat startup. Rutin kalibrasi osilator sangat rewel, jadi berhati-hatilah jika Anda menempuh rute itu. Saya telah memposting beberapa contoh kode untuk itu di bawah jawaban lain.
bathMarm0t
6

Saat Anda menggunakan UART, osilator kristal akan disarankan. Jika bukan karena itu, Anda dapat menggunakan osilator internal. Beberapa MCU memiliki osilator internal yang dipangkas pabrik, yang dapat cocok untuk operasi UART.

Leon Heller
sumber
2
Lihat juga catatan aplikasi ini pada waktu UART: maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl
Nah, UART hanya untuk komunikasi dengan tampilan serial super sederhana yang berjalan pada 9600bps ... Saya pikir saya akan berakhir memesan osilator dan segalanya tetapi melihat apakah itu akan berhasil tanpanya
Earlz
3

"Tidak peka waktu". UART sangat sensitif terhadap waktu. Anda akan mendapatkan sampah lengkap jika tidak disinkronkan dengan tepat.

Opsi 1: Gunakan kristal normal. Ganti sekering pilih jam dengan tepat. Pilihan kristal tergantung pada baud apa yang ingin Anda gunakan / seberapa cepat Anda ingin benda ini pergi. Ada "kristal ajaib" yang akan memberi Anda 0% kesalahan untuk harga standar (jika mereka diproduksi dengan sempurna). Lihat tabel di Bagian 20 [USART0] untuk info lebih lanjut (Anda telah membaca lembar data .... benar ???) :).

masukkan deskripsi gambar di sini

Opsi 2: Anda dapat mengkalibrasi osilator internal menggunakan kristal 32khz jika daya bermasalah. Dengan 32khz Anda bisa mendapatkan arus uA dalam mode tidur (Saya sudah turun ke ~ 2uA). Anda harus mensetup kalibrasi rutin yang melibatkan timer mulai / berhenti dan timer2 bergantian ke mode asinkron.

Kode 328P mungkin berbeda ... fungsi ini saat ini bekerja pada 48/88 (dengan definisi F_CPU / baud yang sesuai. Agak jelek / tidak sepenuhnya di-refactored tapi saya telah belajar lebih baik daripada mengacaukan hal-hal yang berfungsi saat Anda sedang pada tenggat waktu. Cari di forum AVRFreaks untuk "tune 32khz crystal" sesuatu seperti itu. Ini hanya rasa untuk apa yang akan Anda masuki ... Belum tentu apa yang akan berhasil.

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;
}
bathMarm0t
sumber
2

Perlu juga dicatat bahwa kristal membutuhkan waktu lama untuk memulai. Itu sebenarnya karena presisi: hanya membutuhkan energi dari pita frekuensi yang sangat sempit. Ini bisa menjadi beban untuk hal-hal yang dioperasikan dengan baterai di mana Anda membangunkan MCU untuk waktu yang sangat singkat setiap saat: menunggu ms pada daya penuh menarik untuk memulai kristal adalah kerugian bersih. Resonator keramik lebih akurat daripada osilator RC internal tetapi kurang dari kristal, dan mulai sesuai.

Tentu saja atmega 16MHz meminum lebih banyak jus dan membutuhkan tegangan lebih tinggi daripada yang 8MHz, tetapi kristal 8MHz (atau lebih rendah, hingga 32kHz) tersedia; pilihan belaka ini juga bisa menjadi penghemat energi.

Nicolas D
sumber
0

Jika Anda tidak membutuhkan banyak waktu atau ketepatan waktu, tidak perlu osilator eksternal. Saat membongkar beberapa printer lama, saya kebetulan melihat banyak IC tetapi tidak ada osilator tunggal di papan.

SetKent
sumber
0

Saya kira Anda sudah melihat catatan aplikasi ini: AVR053: Kalibrasi osilator RC internal .

Saya kira dari itu, dan catatan aplikasi dari komentar @drxzcl di atas, Anda harus dapat memutuskan secara teoritis apa yang benar.

Vorac
sumber
Di mana sudah ada jawaban yang diterima, Anda harus mencoba untuk mengatakan sesuatu yang lebih, selain itu tidak terlalu berguna
clabacchio
@clabacchio - jawaban ini berumur dua hari, dan tanggal yang diterima dari kemarin. Itu tidak dapat diterima saat ini diposting.
stevenvh
@stevenvh benar, saya tidak menyadari itu hanya edit; meskipun, itu adalah jawaban yang tidak lengkap
clabacchio
@clabacchio - "jawaban tidak lengkap". Sepakat! Saya tidak dapat menemukan "Anda harus dapat memutuskan" sangat membantu.
stevenvh
@clabacchio - Hei, punyaku juga mengatakan "2 hari yang lalu" sekarang. Semenit yang lalu tertulis "dijawab kemarin". Harus tepat 48 jam! :-)
stevenvh