Atmega328P: Internen Oszillator kalibrieren mit Boardmitteln

Der interne Oszillator des Atmega328P (allgemeiner: aller AVRs) ermöglicht es einem den Mikrocontroller mit einer Frequenz von bis zu 8 MHz laufen zu lassen. Die Werkseinstellung sind 1 MHz und diese sind auf ±10% genau justiert. Dies genügt für die allermeisten Fälle auch es kann aber auch Aufgaben geben, die ein genaueres Timing erfordern.

Einer dieser Fälle wäre die Verwendung des UART. Je nach Mode darf dieser nur einen Fehler von ca. 1% aufweisen da es sonst zu Übertragungsfehler kommt, ist aber die Abweichung des Oszillator schon größer muss diese kalibriert werden. Mit Hilfe des OSCCAL-Registers ist man in der Lage den internen RC-Oszilator nachzutunen.
In der AVR053 wird die Kalibrierprozedur mit Hilfe eines genau bekannten externen Taktes beschrieben. Das Problem hierbei: Nicht jeder hat zwingend einen passenden Frequenzgenerator im Bastelkeller stehen.

Mit Hilfe des UART lässt sich der interne Oszillator mit einem kleinen Programm direkt in der Zielschaltung kalibrieren. Hierzu lässt man einfach in einer Schleife das OSCCAL-Register von 0x00 bis 0x7f bzw. von 0x80 bis 0xff hoch laufen (vgl. Datasheet) und schickt mit jeder Itteration den OSCCAL-Wert via UART2USB z.B. auf einen PC. Das Ergebnis kann dann wie folgt aussehen.

Sobald die Übertragung lesbar wird hat man einen für die dann am Atmega anliegende Spannung und herrschende Temperatur einen schon recht brauchbaren Value für das OSCCAL-Register. Parktisch würde man dann den mittleren Wert der im obigen Beispiel fehlerfreien Übertragungen verwenden, hier also etwa den Wert 109.
So lässt sich also auch ganz ohne Frequenzgenerator der Kalibrierwert für den internen RC-Oszillator ermitteln.

### Programm zur Bestimmung von OSCCAL ohne Frequenzgenerator ###

#include <stdlib.h>
#include <avr/io.h>

#include "uart.h"

int main(void) {
    uartSetup(9600);
    char valueToSend[5];
    for (uint8_t i=0x00; i<0x7f; i++) {
        OSCCAL = i;
        sendString("OSCCAL is now: ");
        itoa(OSCCAL,
             valueToSend,
             10);
        sendString(valueToSend);
        sendString("\r\n");
        
    }
	for (;;) {
	}
	return 0; // never reached
}
Dieser Beitrag wurde unter Programmierung abgelegt und mit , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Time limit is exhausted. Please reload the CAPTCHA.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.