ATmega8:s interna oscillator

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
mrhedin
Inlägg: 114
Blev medlem: 3 maj 2005, 19:46:24
Ort: Trollhättan/Kiruna
Kontakt:

ATmega8:s interna oscillator

Inlägg av mrhedin »

Jag har skrivit en delayfunktion i C som skall fördröja med det värde den blir anropad med. Testat att köra den för sig själv i AVRStudio med en sekund och AVRStudions stopwatch säger 1000.07ms.

Problemet är att om jag kör säg 10 min på labbplatta med tidtagarur så slår det med ca 5s. Jag använder den interna oscillatorn i atmegan på 8MHz och hörde att nån sa att den är inte noggrannare än så. Stämmer det eller är det jag som har programmerat fult så att det blir så i praktiken?

Kod: Markera allt

void delay_s(unsigned int x)
{
	setbit(TCCR1B, CS10); // Starta Timer1, Prescaler 1024. TCLK=7812,5Hz @ Fosc 8MHz.
	clearbit(TCCR1B, CS11); // Starta Timer1, Prescaler 1024. TCLK=7812,5Hz @ Fosc 8MHz.
	setbit(TCCR1B, CS12); // Starta Timer1, Prescaler 1024. TCLK=7812,5Hz @ Fosc 8MHz.
	
	while(x > 0)
	{
		setbit(TIFR, TOV1); // Cleara overflowflagga.
		TCNT1=57723; // Laddar med värde för att få en sekund.
		while(!checkbit(TIFR, TOV1)) {} // Vänta på overflowflagga.
		x--;
	}	

	clearbit(TCCR1B, CS10); // Timer1 avstängd.
	clearbit(TCCR1B, CS11); // Timer1 avstängd.
	clearbit(TCCR1B, CS12); // Timer1 avstängd.
}
Användarvisningsbild
Greensilver
Inlägg: 1305
Blev medlem: 21 januari 2005, 21:24:57
Ort: Sverige
Kontakt:

Inlägg av Greensilver »

Man kan kalibrera klockan mjukvarumässigt. Det finns info på www.atmel.com om hur man gör. Har en kodsnutt någonstans dock ej för Mega8. Skall kika om jag hittar den. Enligt databladet till Mega32 går det att få den att gå med en noggrannhet på 2%.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Jag använder den interna oscillatorn i atmegan på 8MHz och hörde
> att nån sa att den är inte noggrannare än så.

Vadå "hörde" ??
Du läste väl i databladet ? Vad sa det ?
Användarvisningsbild
BEEP
EF Sponsor
Inlägg: 1593
Blev medlem: 21 januari 2006, 16:57:56
Ort: Mölndal

Inlägg av BEEP »

Det här är det enda som jag hittade i databladet allt annat var bara om hur mycket frekvensen ändrades vid olika temperaturer och spänningar.
Oscillator
The calibrated internal RC Oscillator provides a fixed 1.0, 2.0, 4.0, or 8.0 MHz clock. All
frequencies are nominal values at 5V and 25°C. This clock may be selected as the system
clock by programming the CKSEL fuses as shown in Table 9. If selected, it will
operate with no external components. The CKOPT fuse should always be unprogrammed
when using this clock option. During reset, hardware loads the calibration byte
into the OSCCAL register and thereby automatically calibrates the RC Oscillator. At 5V,
25°C and 1.0 MHz Oscillator frequency selected, this calibration gives a frequency
within ± 1% of the nominal frequency.
Användarvisningsbild
Greensilver
Inlägg: 1305
Blev medlem: 21 januari 2005, 21:24:57
Ort: Sverige
Kontakt:

Inlägg av Greensilver »

Min kod hjälper dig nog inte heller är jag rädd, den använder en extern kristall för att kalibrera. :(

Kod: Markera allt

//Calibrate the internal OSCCAL byte, using the external 
//32,768 kHz crystal as reference
void OSCCAL_calibration(void)
{
    unsigned char calibrate = 0;//FALSE;
    int temp;
    unsigned char tempL;

    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)
    
    OCR2A = 200;            // set timer2 compare value 

    TIMSK0 = 0;             // delete any interrupt sources
        
    TCCR1B = (1<<CS10);     // start timer1 with no prescaling
    TCCR2A = (1<<CS20);     // start timer2 with no prescaling

    while((ASSR & 0x01) | (ASSR & 0x04));       //wait for TCN2UB and TCR2UB to be cleared

    // wait for external crystal to stabilise
	for(int i = 0; i < 10; i++)
			_delay_loop_2(30000);   
			
    while(!calibrate)
    {
        cli(); // mt __disable_interrupt();  // 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
           
        while ( !(TIFR2 && (1<<OCF2A)) );   // wait for timer2 compareflag
    
        TCCR1B = 0; // stop timer1

        sei(); // __enable_interrupt();  // enable global interrupt
    
        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;
        }
    
        if (temp > 6250)
        {
            OSCCAL--;   // the internRC oscillator runs to fast, decrease the OSCCAL
        }
        else if (temp < 6120)
        {
            OSCCAL++;   // the internRC oscillator runs to slow, increase the OSCCAL
        }
        else
            calibrate = 1;//TRUE;   // the interRC is correct
    
        TCCR1B = (1<<CS10); // start timer1
    }
}
Användarvisningsbild
Rohan
Inlägg: 1065
Blev medlem: 7 april 2004, 08:24:39
Ort: Eksjö, Småland
Kontakt:

Inlägg av Rohan »

Din kod är det nog inget fel på men om du funderar lite så kanske det ger sig vad som är fel.

Du säger att det blir 5 sekunder fel på 10 minuter. 10 minuter är 600 sekunder. Vad säger databladet? Jo, att vid 5V och 25°C så ska det inte bli mer än 1% fel. Hur mycket är 1%? Precis, 6 sekunder. Det har alltså blivit lite bättre än databladet och du har säkert inte ens haft 25°C.

När de skriver nominellt och anger en spänning och temperatur så innebär det nästan ingenting, tyvärr. :cry: Den interna oscillatorn är väldigt temperaturberoende och även beroende av spänningen.

Slutsats: För bättre precision behöver du en extern kristall.
mrhedin
Inlägg: 114
Blev medlem: 3 maj 2005, 19:46:24
Ort: Trollhättan/Kiruna
Kontakt:

Inlägg av mrhedin »

Ja så verkar det faktiskt vara. Tack för hjälpen...
Skriv svar