Usando o ATMega328 com o oscilador interno?

18

Eu tenho um projeto que acho que seria mais adequado para um ATMega328P. No entanto, em todos os projetos simples que eu já vi, as pessoas sempre conectam um oscilador externo de 16 MHz. Pelo que posso ver, ele deve ter um oscilador interno de 8MHz. Meu projeto não exige muito poder de processamento, nem o tempo precisa ser muito preciso (exceto para um UART e I2C). Eu também tenho um programador, então não preciso me preocupar com os gerenciadores de inicialização.

Existe alguma razão para eu usar um oscilador externo?

Earlz
fonte

Respostas:

20

O que você não diz é qual é a precisão deste oscilador interno. Levei algum tempo para encontrá-lo na folha de dados , na página 369.

10%. Dez por cento! E isso para um oscilador calibrado? Isso é horrível. Não é razoável esperar um erro tão baixo quanto 1% para isso . Microchip / Atmel fornece um documento para calibrar você mesmo o oscilador com precisão de 1%.

I2C é um protocolo síncrono e a precisão do tempo não é relevante desde que sejam respeitados os tempos mínimo e máximo de pulso.
O UART, por outro lado, é assíncrono e, portanto, a precisão do tempo é realmente importante. A maioria dos UARTs permite um erro de meio bit no último bit (o bit de parada), ou seja, 5% para uma transmissão de 10 bits.

O oscilador calibrado de fábrica não funciona aqui. Você terá que passar pelo procedimento de calibração para chegar a 1%. Nesse caso, você pode usar o oscilador interno. Caso contrário, você terá que usar um cristal.

stevenvh
fonte
1
Deixe-me reforçar o que está sendo dito aqui. Economize seu tempo e dor de cabeça e apenas pegue um cristal. Se a energia é uma preocupação, use um relógio de 32khz (6PF para 48/88/168 ... não tenho certeza sobre o 328. verifique a folha de migração) para ajustar o oscilador interno na inicialização. A rotina de calibração do oscilador é muito complicada, portanto, tome cuidado se você seguir esse caminho. Eu publiquei um código de exemplo para ele abaixo de outra resposta.
precisa saber é o seguinte
6

Como você está usando um UART, é recomendável um oscilador de cristal. Se não fosse por isso, você poderia usar o oscilador interno. Alguns MCUs possuem osciladores internos de fábrica, que podem ser adequados para a operação UART.

Leon Heller
fonte
2
Veja também esta nota de aplicativo sobre o tempo do UART: maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl
Bem, o UART é apenas para comunicação com um monitor serial super simples que roda a 9600bps ... Acho que vou acabar encomendando o oscilador e tudo mais, mas vendo se ele funcionará sem ele
Earlz
3

"Não é sensível ao tempo". O UART é muito sensível ao tempo. Você obterá o lixo completo se não for sincronizado adequadamente.

Opção 1: Use um cristal normal. Mude o fusível de seleção do relógio adequadamente. A seleção de cristais depende de qual transmissão você deseja usar / com que rapidez você deseja que isso ocorra. Existem "cristais mágicos" que fornecerão 0% de erro nas taxas padrão (se forem fabricadas perfeitamente). Consulte as tabelas na Seção 20 [USART0] para obter mais informações (você leu a ficha técnica .... certo ???) :).

insira a descrição da imagem aqui

Opção 2: Você pode calibrar o oscilador interno usando um cristal de 32khz, se a energia for uma preocupação. Com 32khz, você pode obter correntes uA no modo de suspensão (eu as reduzi para ~ 2uA). É necessário configurar uma rotina de calibração, que envolve iniciar / parar os cronômetros e alternar o timer2 para o modo assíncrono.

O código 328P pode diferir ... essa função atualmente funciona em 48/88 (com definições de F_CPU / baud apropriadas. É um pouco feio / não é refatorado completamente, mas eu aprendi melhor do que mexer com coisas que funcionam quando você está Pesquise no fórum da AVRFreaks por "sintonizar cristal de 32khz", algo assim: este é apenas um gostinho do que você entrará ... Não necessariamente o que vai funcionar.

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
fonte
2

Note-se também que um cristal demora muito tempo para começar. Na verdade, isso é devido à sua precisão: ele apenas usa energia de uma banda de frequência muito estreita. Isso pode ser um fardo para coisas operadas por bateria, nas quais você acorda o mcu por um período muito curto de vez em quando: esperar alguns ms com consumo total de energia para o cristal iniciar é uma perda líquida. Os ressonadores de cerâmica são mais precisos que o oscilador RC interno, mas menos que um cristal e iniciam de acordo.

É claro que um atmega de 16 MHz bebe muito mais suco e precisa de uma voltagem mais alta que uma de 8 MHz, mas os cristais de 8 MHz (ou menos, até 32 kHz) estão disponíveis; essa mera escolha também pode ser uma economia de energia.

Nicolas D
fonte
0

Se você não precisa de muito ou tempo preciso, não há necessidade de um oscilador externo. Ao desmontar algumas impressoras antigas, vejo muitos ICs, mas não um único oscilador a bordo.

SetKent
fonte
0

Acho que você já viu esta nota de aplicativo: AVR053: Calibração do oscilador RC interno .

Eu acho que, e a nota do aplicativo do comentário de @drxzcl acima, você deve ser capaz de decidir teoricamente o que é certo.

Vorac
fonte
Onde já existe uma resposta aceita, você deve tentar dizer algo mais, caso contrário não é muito útil
clabacchio
@clabacchio - esta resposta tem dois dias e as datas aceitas de ontem. Não pode ter sido aceito quando este foi publicado.
Stevenvh 25/05
@stevenvh certo, eu não sabia que era apenas uma edição; porém, é uma resposta incompleta
clabacchio
@clabacchio - "resposta incompleta". Acordado! Não consigo encontrar "você deve ser capaz de decidir" muito útil.
Stevenvh 25/05
@clabacchio - Ei, o meu também diz "2 dias atrás" agora. Há um minuto atrás, dizia "respondeu ontem". Devem ter sido exatamente 48 horas! :-)
stevenvh