Використовуєте ATMega328 з внутрішнім генератором?


18

У мене є проект, який, на мою думку, найкраще підходить для ATMega328P. Однак у кожному простому проекті, який я бачив, люди завжди підключають 16МГц зовнішній генератор. Як я бачу, він повинен мати внутрішній генератор 8 МГц. Мій проект не вимагає великої потужності для обробки, а також терміни не повинні бути дуже точними (окрім UART та I2C). У мене також є програміст, тому мені не потрібно турбуватися про завантажувачі.

Чи є в мене причина використовувати зовнішній генератор?

Відповіді:


20

Що ви не скажете - це точність цього внутрішнього генератора. Знадобилося певний час, щоб знайти його у таблиці даних на сторінці 369.

10%. Десять відсотків! І що для каліброваного генератора? Це жахливо. Нерозумно очікувати помилок на рівні 1% . Microchip / Atmel надає документ для самостійної калібрування осцилятора з точністю до 1%.

I2C - це синхронний протокол, і точність синхронізації не є важливою, якщо дотримуються мінімальний та максимальний час імпульсів. З іншого боку,
UART є асинхронним , і тоді точність дійсно важлива. Більшість UART допускають половинну бітну помилку в останньому біті (стоп-біті), так що це 5% для 10-бітної передачі.

Фабрично калібрований осцилятор тут робити не буде. Вам доведеться пройти процедуру калібрування, щоб досягти 1%. У такому випадку ви можете використовувати внутрішній генератор. Інші розміри вам доведеться використовувати кристал.


1
Дозвольте мені підкріпити те, що тут говориться. Економте собі час і головний біль і просто отримайте кришталь. Якщо живлення викликає занепокоєння, використовуйте 32-кгазовий годинник-кристал (6PF для 48/88/168 ... не впевнений у 328. перевірити аркуш міграції), щоб настроїти внутрішній генератор при запуску. Процедура калібрування осцилятора дуже вибаглива, тому будьте обережні, якщо ви йдете цим маршрутом. Я розмістив деякий приклад коду під іншою відповіддю.
bathMarm0t

6

Коли ви використовуєте UART, доцільним буде генератор кристалів. Якби не це, ви можете використовувати внутрішній генератор. У деяких MCU встановлені внутрішні генератори, які можуть бути придатні для роботи UART.


2
Дивіться також цю нотатку про час UART: maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl

Ну, UART призначений лише для зв'язку із надзвичайно простим серійним дисплеєм, який працює зі швидкістю 9600bps ... Я думаю, я
закінчу

3

"Не залежно від часу". UART дуже чутливий до часу. Ви отримаєте повне сміття, якщо воно не буде синхронізовано належним чином.

Варіант 1: Використовуйте звичайний кристал. Змініть годинник відповідно. Вибір кристалів залежить від того, яку боду ви хочете використовувати / як швидко ви хочете, щоб ця річ пішла. Є "магічні кристали", які дадуть вам 0% помилок за стандартних норм (якщо вони виготовлені ідеально). Дивіться таблиці в Розділі 20 [USART0] для отримання додаткової інформації (ви прочитали таблицю .... правильно ???) :).

введіть тут опис зображення

Варіант 2: Ви можете калібрувати внутрішній генератор, використовуючи кристал 32 кГц, якщо живлення викликає занепокоєння. За допомогою 32 кГц ви можете отримувати струми uA в режимі сну (я звів їх до ~ 2uA). Вам потрібно встановити процедуру калібрування, хоча вона включає в себе запуск / зупинку таймерів та чергування таймера2 в асинхронний режим.

Код 328P може відрізнятися ... ця функція в даний час працює на 48/88 (з відповідними визначеннями F_CPU / boud. Це трохи некрасиво / не відремонтоване повністю, але я навчився краще, ніж закручувати речі, які працюють, коли ти на терміні. Шукайте на форумі AVRFreaks щось "подібне 32хЗ кристала". Це просто смак того, що ви будете вникати ... Не обов’язково те, що буде працювати.

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 дуже короткий час: очікування повідомлення на повну потужність для запуску кристала - це чиста втрата. Керамічні резонатори є більш точними, ніж внутрішній RC-генератор, але менше, ніж кристал, і запускаються відповідно.

Звичайно, атмега потужністю 16 МГц п'є набагато більше соку і потребує більш високої напруги, ніж 1 МГц, але доступні кристали 8 МГц (або нижче, до 32 кГц); цей простий вибір також може бути економією енергії.


0

Якщо вам не потрібні великі або точні терміни, немає необхідності у зовнішньому генераторі. Розбираючи деякі старі принтери, я часто бачу багато мікросхем, але жодного осцилятора на борту.


0

Я думаю, ви вже бачили примітку цього додатка: AVR053: Калібрування внутрішнього RC-генератора .

Я здогадуюсь про це, і примітка додатка з коментаря @drxzcl вище, ви повинні мати можливість теоретично вирішити, що правильно.


Там, де вже є прийнята відповідь, слід спробувати сказати щось більше, інакше це не дуже корисно
clabacchio

@clabacchio - у цій відповіді два дні, а дати прийняті з вчорашнього дня. Його не можна було прийняти, коли це було розміщено.
stevenvh

@stevenvh правильно, я не розумів, що це лише редагування; хоча це неповна відповідь
clabacchio

@clabacchio - "неповна відповідь". Домовились! Я не можу знайти "ви повинні мати можливість вирішити" дуже корисно.
stevenvh

@clabacchio - Гей, моє також зараз говорить "2 дні тому". Хвилину тому вона сказала "відповіла вчора". Повинні пройти рівно 48 годин! :-)
stevenvh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.