Wie konfiguriere ich den internen Oszillator in einem PIC16F616?

Ich möchte den internen Oszillator im PIC16F616 in einer 8-MHz-Konfiguration verwenden und die E/A-Funktion auf RA4und haben RA5. Ich habe das Datenblatt durchgelesen und kann nicht finden, was ich falsch mache.

Soweit ich die folgenden Informationen verstehe, TMR0sollte es alle 500 ns inkrementieren und einen Interrupt erzeugen, wenn es von "0xFF" auf "0x00" überläuft. RA4Pin schaltet jedoch etwa alle 20 us um.

Aus dem Datenblatt:

5.1.1

8-BIT-TIMER-MODUS

Wenn es als Timer verwendet wird, erhöht das Timer0-Modul jeden Befehlszyklus (ohne Prescaler).

Der Zeitgebermodus wird ausgewählt, indem das T0CS-Bit des OPTION-Registers auf "0" gelöscht wird.

Auch;

Hinweis: Der in das TMR0-Register geschriebene Wert kann angepasst werden, um die Verzögerung von zwei Befehlszyklen beim Schreiben von TMR0 zu berücksichtigen.

Blockdiagramm des TIMER0/WDT Prescalers

Hier ist mein Code, mein Compiler ist MPLAB XC8. :

#include <xc.h>
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_8MHZ & BOREN_ON);

void interrupt myInterrupt(void)
{
    if (T0IE && T0IF)
    {
        RA4 = ~RA4;
        TMR0 = 254;
        T0IF = 0;
    }
}

void main()
{
    TRISA = 0;
    ANSEL = 0;

    PSA = 1; // Prescaler Assignment bit : 1 = Prescaler is assigned to the WDT, 0 = Prescaler is assigned to the Timer0 module
    T0CS = 0; // T0CS: TMR0 Clock Source Select bit : 0 = Internal instruction cycle clock (FOSC/4), 1 = Transition on T0CKI pin
    T0IE = 1; //T0IE: Timer0 Overflow Interrupt Enable bit
    GIE = 1; //GIE: Global Interrupt Enable bit

    while (1);
}
Ist das _config() richtig? ist das '|' Operator statt '&' Operator?
Seien Sie vorsichtig, einige Compiler verwenden Schreibschutz.
@sandundhammika, MPLAB XC8 Benutzerhandbuch sagt:Multiple attributes can be selected by ANDing them together.

Antworten (2)

Das Setzen von TMR0 auf einen festen Wert in der Interrupt-Routine ist eine schlechte Idee, wenn Sie einen zuverlässigen periodischen Interrupt wünschen. Sie setzen es auf 254. Das erzeugt 2 tote Zyklen und benötigt dann 2 weitere Zyklen zum Überlaufen. Die Unterbrechungsbedingung wird gesetzt, lange bevor der Prozessor zurückkommen und weitere 254 in den Zeitgeber stopfen kann. Sie verwenden einen Compiler (tun Sie das nicht, wenn Sie sich einzelne Anweisungen ansehen), sodass Sie nicht wissen, wie viele Anweisungen zum Verlassen der Interrupt-Routine und wie viele beim Eintritt vorhanden sind. 20 µs bedeuten 40 Befehlszyklen. Das klingt hoch, aber Sie verwenden einen Compiler , also haben Sie bereits gesagt, dass Sie sich nicht um Effizienz kümmern und das Recht aufgegeben haben, Zyklen zu zählen.

Wenn Sie überprüfen möchten, ob der PIC mit der richtigen Taktrate läuft, lassen Sie den Timer 0 frei laufen, ohne ihn zu berühren. Das sollte alle 256 Befehlszyklen oder alle 128 µs unterbrechen.

Wenn Sie einen zuverlässigen periodischen Interrupt wünschen, sollte die erste Reaktion darin bestehen, Timer 2 zu verwenden. Dafür ist er da und hat ein eingebautes Periodenregister. Wenn Sie Timer 2 für etwas anderes benötigen, können Sie immer noch Timer 0 verwenden, aber jeden Interrupt hinzufügen , nicht seinen Wert zurücksetzen. Auf diese Weise geht die Zeit vom Ablauf des Timers bis zum erneuten Schreiben nicht verloren. Erwarten Sie auch keine lächerlich kurze Zeit wie 4 Unterrichtszyklen. Der PIC kann nicht so schnell in einen Interrupt ein- und aussteigen, auch ohne den Zustand zu speichern.

Sie können ohne einen Compiler nicht in C schreiben, also gebe ich es auf :) Scheint, dass meine Konfiguration registriert und der Code in Ordnung ist, und es gibt, was es sollte, aber meine Erwartungen sind falsch. Ich habe noch nie einen Timer außer Timer0 berührt, seit ich mit Mikrocontrollern angefangen habe, ich werde mir die anderen ansehen. Danke für die tolle Antwort.
'TMR0 = 254;' , ich denke, es ist das falsche !
@sandundhammika, nein, mein ursprünglicher TMR0-Wert war 235, und er funktionierte aus den von Olin erwähnten Gründen nicht wie berechnet.

Einfacher Wechselplatz für void interrupt myInterrupt(void) nach Hauptfunktion.

Können Sie erklären, wie und warum das die Lösung ist?