내부 발진기와 함께 ATMega328을 사용합니까?


18

ATMega328P에 가장 적합한 프로젝트가 있습니다. 그러나 내가 본 모든 간단한 프로젝트에서 사람들은 항상 16MHz 외부 발진기를 연결합니다. 내가 볼 수 있듯이 8MHz 내부 발진기가 있어야합니다. 내 프로젝트에는 많은 처리 능력이 필요하지 않으며 타이밍이 매우 정확해야 할 필요도 없습니다 (UART 및 I2C 제외). 프로그래머도 있으므로 부트 로더에 대해 걱정할 필요가 없습니다.

외부 발진기를 사용해야 할 이유가 있습니까?

답변:


20

당신이 말하지 않는 것은이 내부 발진기의 정확성입니다. 데이터 시트 , 369 페이지 에서 그것을 찾는 데 시간이 걸렸습니다 .

10 % 10! 그리고 교정 된 발진기의 경우? 이것은 끔찍하다. 이것에 대해 1 %의 낮은 오류를 예상하는 것은 무리가 없습니다 . Microchip / Atmel은 발진기를 직접 1 % 정확도로 교정하기위한 문서 를 제공합니다 .

I2C동기식 프로토콜이며 최소 및 최대 펄스 시간이 고려되는 한 타이밍 정확도는 관련이 없습니다. 반면에
UART비동기식 이므로 타이밍 정확도가 중요합니다. 대부분의 UART는 마지막 비트 (정지 비트)에서 반 비트 오류를 ​​허용하므로 10 비트 전송의 경우 5 %입니다.

출고시 교정 된 발진기는 여기에서 수행되지 않습니다. 1 %에 도달하려면 교정 절차를 거쳐야합니다. 이 경우 내부 발진기를 사용할 수 있습니다. 그렇지 않으면 크리스탈을 사용해야합니다.


1
여기서 말하는 내용을 강화하겠습니다. 시간과 두통을 피하고 결정을 얻으십시오. 전력이 문제가되는 경우 32khz 시계 크리스털 (48/88/168의 경우 6PF ... 328에 대해 잘 모르겠습니다. 마이그레이션 시트 확인)을 사용하여 시작시 내부 발진기를 조정하십시오. 오실레이터 캘리브레이션 루틴은 매우 까다롭기 때문에 해당 경로로 이동하면주의하십시오. 다른 답변 아래에 예제 코드를 게시했습니다.
bathMarm0t

6

UART를 사용함에 따라 수정 발진기가 권장됩니다. 그렇지 않은 경우 내부 발진기를 사용할 수 있습니다. 일부 MCU에는 공장 트리밍 된 내부 발진기가 있으며 UART 작동에 적합합니다.


2
UART 타이밍에 대한이 앱 노트를 참조하십시오 : maxim-ic.com/app-notes/index.mvp/id/2141
drxzcl

음, UART는 9600bps에서 실행되는 매우 간단한 직렬 디스플레이와의 통신에만 사용됩니다. 오실레이터와 모든 것을 주문하지만 그 없이도 작동하는지 확인합니다.
Earlz

3

"시간에 민감하지 않다". UART는 시간에 매우 민감합니다. 적절하게 동기화되지 않으면 완전한 쓰레기를 얻게됩니다.

옵션 1 : 일반 크리스탈을 사용하십시오. 시계 선택 퓨즈를 적절히 변경하십시오. 크리스탈 선택은 사용하려는 보드 /이 속도를 얼마나 빨리 원하는지에 따라 다릅니다. 표준 속도 (완벽하게 제조 된 경우)에 대해 0 %의 오차를주는 "마법의 결정"이 있습니다. 자세한 정보는 섹션 20 [USART0]의 표를 참조하십시오 (데이터 시트를 읽었습니다 .... right ???) :).

여기에 이미지 설명을 입력하십시오

옵션 2 : 전력이 중요한 경우 32khz 크리스털을 사용하여 내부 발진기를 교정 할 수 있습니다. 32khz를 사용하면 휴면 모드에서 uA 전류를 얻을 수 있습니다 (~ 2uA로 낮춤). 타이머를 시작 / 중지하고 timer2를 비동기 모드로 교체하는 교정 루틴을 설정해야합니다.

328P 코드는 다를 수 있습니다 ...이 기능은 현재 48/88에서 작동합니다 (적절한 F_CPU / baud 정의 사용) 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를 깨운 다음 ​​결정을 시작하기 위해 최대 전력 소비에서 ms를 기다리는 것은 순 손실입니다. 세라믹 공진기는 내부 RC 발진기보다 정확하지만 크리스털보다는 적으며 그에 따라 시작됩니다.

물론 16MHz atmega는 훨씬 더 많은 주스를 마시고 8MHz 주스보다 높은 전압을 필요로하지만 8MHz (또는 32kHz 이하) 결정을 사용할 수 있습니다. 이 단순한 선택은 또한 에너지 절약이 될 수 있습니다.


0

많거나 정확한 타이밍이 필요하지 않은 경우 외부 발진기가 필요하지 않습니다. 오래된 프린터를 분해하는 동안 많은 IC가 있지만 보드에는 단일 발진기가 없습니다.


0

당신은 이미이 응용 프로그램 노트를 본 것 같아요 : AVR053 : 내부 RC 발진기의 교정 .

나는 그것을 추측하고 위의 @ drxzcl의 의견에서 나온 응용 프로그램 노트에서 이론적으로 옳은 것을 결정할 수 있어야합니다.


이미 받아 들여진 대답이있는 경우, 더 많은 것을 말하려고 노력해야합니다. 그렇지 않으면 그다지 유용하지 않습니다
clabacchio

@clabacchio-이 답변은 2 일이었으며 어제부터 수락 된 날짜입니다. 게시 된 날짜로는 수락 할 수 없습니다.
stevenvh

@stevenvh 맞다, 나는 그것이 단지 편집이라는 것을 몰랐다. 그러나, 그것은 불완전한 대답입니다
clabacchio

@clabacchio- "불완전한 답변". 동의했다! "당신이 결정할 수 있어야한다"는 것이 매우 도움이되지 않습니다.
stevenvh

@clabacchio-이봐, 나도 "2 일 전"이라고 말합니다. 1 분 전에 "어제 대답했습니다"라고했습니다. 정확히 48 시간이었을 것입니다! :-)
stevenvh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.