Используя ATMega328 с внутренним генератором?


18

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

Есть ли причина для меня использовать внешний генератор?

Ответы:


20

То, что вы не говорите, какова точность этого внутреннего генератора. Мне потребовалось некоторое время, чтобы найти его в таблице на странице 369.

10%. Десять процентов! А что за калиброванный генератор? Это ужасно Для этого не является необоснованным ожидать ошибки в 1% . Microchip / Atmel предоставляет документ для калибровки генератора с точностью до 1%.

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

Заводской калиброванный генератор здесь не подходит. Вам придется пройти процедуру калибровки, чтобы получить 1%. В этом случае вы можете использовать внутренний генератор. В противном случае вам придется использовать кристалл.


1
Позвольте мне подтвердить, что здесь говорится. Сэкономьте время и головную боль и просто получите кристалл. Если есть проблема с питанием, используйте 32 кГц часовой кристалл (6PF для 48/88/168 ... не уверен насчет 328. проверьте лист миграции), чтобы настроить внутренний генератор при запуске. Процедура калибровки генератора очень привередлива, поэтому будьте осторожны, если вы идете по этому пути. Я опубликовал пример кода ниже другого ответа.
bathMarm0t

6

Поскольку вы используете UART, рекомендуется использовать кварцевый генератор. Если бы не это, вы могли бы использовать внутренний генератор. Некоторые микроконтроллеры имеют встроенные на заводе внутренние генераторы, которые могут быть пригодны для работы UART.


2
См. Также это примечание к приложению о сроках UART: maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl

Ну, UART предназначен только для связи с очень простым последовательным дисплеем, который работает на скорости 9600 бит / с ... Я думаю, что в конечном итоге я закажу генератор и все, кроме как
посмотрю,

3

«Не чувствителен ко времени». UART очень чувствителен ко времени. Вы получите полный мусор, если он не синхронизирован должным образом.

Вариант 1. Используйте обычный кристалл. Измените часы, выберите предохранитель соответствующим образом. Выбор кристалла зависит от того, какую скорость передачи вы хотите использовать / как быстро вы хотите, чтобы эта вещь шла. Есть «магические кристаллы», которые дают вам 0% погрешности для стандартных ставок (если они изготовлены идеально). См. Таблицы в Разделе 20 [USART0] для получения дополнительной информации (вы прочитали таблицу ... правильно ???) :).

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

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

Код 328P может отличаться ... эта функция в настоящее время работает на 48/88 (с соответствующими определениями F_CPU / бод. Это немного некрасиво / не полностью переработано, но я научился лучше, чем разбираться с вещами, которые работают, когда вы в срок. Найдите на форуме AVRFreaks "tune 32khz crystal" что-то в этом роде. Это всего лишь вкус к тому, что вы получите ... Не обязательно, что сработает.

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-генератор, но меньше, чем кристалл, и запускаются соответственно.

Конечно, atmega 16 МГц пьет намного больше сока и требует более высокого напряжения, чем 8 МГц, но доступны кристаллы 8 МГц (или ниже, вплоть до 32 кГц); этот простой выбор также может быть энергосберегающим.


0

Если вам не нужно много или точное время, вам не нужен внешний генератор. Разбирая некоторые старые принтеры, я вижу много микросхем, но ни одного генератора на борту.


0

Я думаю, вы уже видели это примечание к приложению: AVR053: Калибровка внутреннего RC генератора .

Я полагаю из этого, и из примечания к приложению из комментария @drxzcl выше, вы сможете теоретически решить, что правильно.


Там, где уже есть принятый ответ, вы должны попытаться сказать что-то еще, иначе это не очень полезно
клабаккио

@clabacchio - этому ответу два дня, и принятые даты со вчерашнего дня. Это не могло быть принято, когда это было опубликовано.
Стивенвх

@ stevenvh верно, я не понимал, что это просто редактирование; хотя, это неполный ответ
клабаккио

@clabacchio - «неполный ответ». Согласовано! Я не могу найти "вы должны быть в состоянии решить" очень полезным.
Stevenvh

@clabacchio - Эй, мой также говорит "2 дня назад" сейчас. Минуту назад он сказал «ответил вчера». Должно быть, было ровно 48 часов! :-)
stevenvh
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.