Vous utilisez l'ATMega328 avec l'oscillateur interne?

18

J'ai un projet qui je pense serait le mieux adapté pour un ATMega328P. Cependant, dans chaque projet simple que j'ai vu, les gens connectent toujours un oscillateur externe à 16 MHz. D'après ce que je peux voir, il devrait avoir un oscillateur interne à 8 MHz. Mon projet ne nécessite pas beaucoup de puissance de traitement, et le timing n'a pas besoin d'être très précis (sauf pour un UART et I2C). J'ai également un programmeur, donc je n'ai pas besoin de me soucier des chargeurs de démarrage.

Y a-t-il une raison pour moi d'utiliser un oscillateur externe?

Earlz
la source

Réponses:

20

Ce que vous ne dites pas, c'est quelle est la précision de cet oscillateur interne. Il m'a fallu un certain temps pour le trouver dans la fiche technique , page 369.

dix%. Dix pour-cents! Et cela pour un oscillateur calibré? C'est affreux. Il n'est pas déraisonnable de s'attendre à une erreur aussi faible que 1% pour cela . Microchip / Atmel fournit un document pour calibrer vous-même l'oscillateur à 1% de précision.

I2C est un protocole synchrone , et la précision de synchronisation n'est pas pertinente tant que les temps d'impulsion minimum et maximum sont respectés.
L'UART, quant à lui, est asynchrone , et la précision du timing est donc importante. La plupart des UART autorisent une erreur d'un demi-bit dans le dernier bit (le bit d'arrêt), ce qui représente 5% pour une transmission sur 10 bits.

L'oscillateur calibré en usine ne fera pas l'affaire ici. Vous devrez suivre la procédure d'étalonnage pour atteindre 1%. Dans ce cas, vous pouvez utiliser l'oscillateur interne. Sinon, vous devrez utiliser un cristal.

Stevenvh
la source
1
Permettez-moi de renforcer ce qui est dit ici. Économisez du temps et des maux de tête et obtenez simplement un cristal. Si l'alimentation est un problème, utilisez un cristal de montre de 32 kHz (6PF pour 48/88/168 ... vous n'êtes pas sûr du 328. vérifiez la feuille de migration) pour régler l'oscillateur interne au démarrage. La routine d'étalonnage de l'oscillateur est très difficile, alors faites attention si vous suivez cette voie. J'ai publié un exemple de code pour celui-ci sous une autre réponse.
bathMarm0t du
6

Comme vous utilisez un UART, un oscillateur à cristal serait conseillé. Sinon, vous pourriez utiliser l'oscillateur interne. Certains MCU ont des oscillateurs internes ajustés en usine, qui peuvent convenir au fonctionnement UART.

Leon Heller
la source
2
Voir également cette note d'application sur le timing UART: maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl
Eh bien, l'UART est uniquement pour la communication avec un écran série super simple qui fonctionne à 9600 bps ... Je pense que je vais finir par commander l'oscillateur et tout, mais voir si cela fonctionnera sans lui
Earlz
3

"Pas sensible au temps". L'UART est très sensible au temps. Vous obtiendrez des ordures complètes s'il n'est pas synchronisé correctement.

Option 1: utilisez un cristal normal. Changer le fusible de sélection d'horloge de manière appropriée. La sélection des cristaux dépend du baud que vous souhaitez utiliser / de la vitesse à laquelle vous voulez que cette chose aille. Il y a des "cristaux magiques" qui vous donneront une erreur de 0% pour les taux standard (s'ils sont parfaitement fabriqués). Voir les tableaux de la section 20 [USART0] pour plus d'informations (vous avez lu la fiche technique .... à droite ???) :).

entrez la description de l'image ici

Option 2: vous pouvez calibrer l'oscillateur interne à l'aide d'un cristal de 32 kHz si la puissance est un problème. Avec 32 kHz, vous pouvez obtenir des courants uA en mode veille (je les ai réduits à ~ 2uA). Vous devez cependant configurer une routine d'étalonnage qui implique le démarrage / l'arrêt des minuteries et l'alternance de timer2 en mode asynchrone.

Le code 328P peut différer ... cette fonction fonctionne actuellement sur 48/88 (avec les définitions F_CPU / baud appropriées. C'est un peu moche / pas complètement refactorisé mais j'ai mieux appris que de déconner avec des choses qui fonctionnent quand vous êtes sur une date limite. Rechercher sur le forum AVRFreaks pour "tune 32khz crystal" quelque chose comme ça. C'est juste un avant-goût de ce que vous allez entrer ... Pas nécessairement ce qui va fonctionner.

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
la source
2

Il convient également de noter qu'un cristal prend beaucoup de temps pour démarrer. C'est en fait à cause de sa précision: il ne prend de l'énergie que dans une bande de fréquences très étroite. Cela peut être un fardeau pour les trucs alimentés par batterie où vous réveillez le MCU pendant très peu de temps en temps: attendre un ms à pleine puissance pour que le cristal démarre est une perte nette. Les résonateurs en céramique sont plus précis que l'oscillateur RC interne mais moins qu'un cristal, et démarrent en conséquence.

Bien sûr, un atmega de 16 MHz boit beaucoup plus de jus et a besoin d'une tension plus élevée qu'un 8 MHz, mais des cristaux de 8 MHz (ou moins, jusqu'à 32 kHz) sont disponibles; ce simple choix peut également être un économiseur d'énergie.

Nicolas D
la source
0

Si vous n'avez pas besoin de beaucoup ou de synchronisation précise, il n'est pas nécessaire d'avoir un oscillateur externe. Lors du démontage de certaines anciennes imprimantes, il se trouve que je vois beaucoup de circuits intégrés, mais pas un seul oscillateur à bord.

SetKent
la source
0

Je suppose que vous avez déjà vu cette note d'application: AVR053: Calibration de l'oscillateur RC interne .

J'imagine, et la note d'application du commentaire de @drxzcl ci-dessus, que vous devriez être en mesure de décider théoriquement ce qui est juste.

Vorac
la source
Là où il y a déjà une réponse acceptée, vous devriez essayer d'en dire plus, sinon ce n'est pas très utile
clabacchio
@clabacchio - cette réponse a deux jours et les dates acceptées d'hier. Il ne peut pas avoir été accepté lors de sa publication.
stevenvh
@stevenvh à droite, je ne savais pas que c'était juste un montage; cependant, c'est une réponse incomplète
clabacchio
@clabacchio - "réponse incomplète". D'accord! Je ne trouve pas "vous devriez pouvoir décider" très utile.
stevenvh
@clabacchio - Hé, le mien dit aussi "il y a 2 jours" maintenant. Il y a une minute, il a dit "répondu hier". Ça devait être exactement 48 heures! :-)
stevenvh