Ich programmiere einen PIC18F4520 und habe ihn so eingestellt, dass er eine interne 32-MHz-Uhr verwendet.
Ich brauche einen Zähler, der jede Sekunde tickt, also verwende ich ihn TMR0
für diesen Zweck.
Zur Verwendung TMR0
habe ich folgendes eingestellt:
TMR0
Überlauf.Um den Timer so einzustellen, dass er alle 1 Sekunde zählt, habe ich ihn wie folgt berechnet:
TMR0 = (Required time)/(4 * Timer clock * prescale value)
= 1 / (4 * (1/32000000) * 256)
= 31250
Also, TMR0 = 0xFFFF - 31250
.
Ist das richtig? Wenn nicht, was übersehe ich? Der Code lautet wie folgt:
#pragma code
void main(void)
{
//Set clock frequency
OSCCON |= 0x70; //8 Mhz clock, primary clock
OSCTUNEbits.PLLEN = 1; //4x Multiplier, thus we have 32 Mhz clock
while (!OSCCONbits.IOFS); //Wait until INTOSC is stable.
//Enable TRISA as analog input (For ADC)
TRISA = 0x2F;
//PIN Outputs
TRISB = 0; //Make PORTD as output
//Reset PORTB
PORTB = 0;
//Set ADC
OpenADC(ADC_FOSC_32 & //Fosc/32
ADC_RIGHT_JUST &
ADC_4_TAD, //4xTAD
ADC_CH0 &
ADC_REF_VDD_VSS &
ADC_INT_OFF, ADC_5ANA); //ADC CH0-CH4 Initialized
//Set Timer0
OpenTimer0( TIMER_INT_ON &
T0_16BIT &
T0_SOURCE_INT &
T0_PS_1_256);
//Write Timer
WriteTimer0(CLOCK_TICK);
INTCON2bits.TMR0IP = 1; //TMR0 has high overflow interrupt priority
RCONbits.IPEN = 1; //enable priority levels
INTCONbits.GIEH = 1; //enable high interrupts
//Begin
while (TRUE)
{
}
CloseADC(); //Closing ADC
CloseTimer0();
}
Auf meinem Interrupt-Vektor auf hoher Ebene habe ich Folgendes getan:
#pragma code
#pragma interrupt high_priority_interrupt
void high_priority_interrupt()
{
if (INTCONbits.TMR0IF) //TIMER0 overflowed
{
//Stuff
second += 1;
if (second == 60)
{
minute += 1;
second = 0;
}
if (minute == 60)
{
measure_and_switch();
WriteTimer0(CLOCK_TICK);
minute = 0;
}
INTCONbits.TMR0IF = 0; //Clear TIMER0 overflow bit.
}
}
Im Grunde möchte ich also, dass die Methode alle 2 Minuten measure_and_switch()
ausgeführt wird. Soll ich ihm folgen WriteTimer0()
?
Übrigens: CLOCK_TICK
ist TMR0
(Rechnung von oben).
Danke
Die Antwort ist einfach. Wenn das Überlaufbit auftritt und der Interrupt ausgelöst wird, müssen wir zuerst den Zähler schreiben TMR0
und das TMR0IF
Flag zurücksetzen.
Diese Lösung funktioniert:
#pragma code
#pragma interrupt high_priority_interrupt
void high_priority_interrupt()
{
if (INTCONbits.TMR0IF) //TIMER0 overflowed
{
//Stuff
second += 1;
if (second == 60)
{
minute += 1;
second = 0;
}
if (minute == 60)
{
measure_and_switch();
minute = 0;
}
WriteTimer0(CLOCK_TICK); //Write the count to TMR0.
INTCONbits.TMR0IF = 0; //Clear TIMER0 overflow bit.
}
}
Ich hoffe, das hilft jemandem. :-)
AndrejaKo
Buhake Sindi
AndrejaKo
Buhake Sindi