Ich suche ein wenig Hilfe und Ratschläge zu meinem Code.
Ich verwende C18 in der MPLab-Umgebung, PIC18f4520 mit Fosc bei 4 MHz und usnig timer0 im 16-Bit-Modus, um bis zum Überlauf zu zählen, das Überlaufbit und das Interrupt-Flag zu setzen, dann zu ISR zu springen und eine Variable "count" zu inkrementieren. Dies wird an einen Port mit angeschlossenen LEDs ausgegeben, so dass ich eine visuelle Bestätigung der Programmfunktion erhalten kann.
Die ausgegebene Zählung ist jedoch immer '1' (dh 0x01) und ich glaube, dass die ISR nur einmal auftritt, wenn überhaupt.
Jede Hilfe, die Sie anbieten können, wird am meisten geschätzt.
Hier ist mein Code:
void main (void) /* */
{
TRISA = 0; /* */
TRISC = 0; /* */
TRISB = 0;
TRISD = 0x00;
RTOS();
}
void low_interrupt (void)
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interruptlow timer_isr
void timer_isr (void)
{
INTCONbits.TMR0IF = 0;
count = count++;
LATD = count;
RTOS();
}
void RTOS (void)
{
T0CONbits.T08BIT = 0; // 16-bit timer
T0CONbits.T0CS = 0; // increment on instruction cycle input
T0CONbits.T0SE = 0; // increment on low--> high transition of clock
T0CONbits.PSA = 1; // T0 prescaler not assigned i.e. 1:1 prescaler.
RCONbits.IPEN = 1; //Enable Interrupt Priorities
INTCONbits.GIEL = 1; //Enable Low Priority Interrupt
INTCONbits.GIE = 1; //Enable Global Interrupts
INTCONbits.TMR0IE = 1; //Enable Timer0 Interrupt
INTCON2bits.TMR0IP = 0; //TMR0 set to Low Priority Interrupt
INTCONbits.TMR0IF = 0; // T0 int flag bit cleared before starting
T0CONbits.TMR0ON = 1; // timer0 START
while (1);
}
Vielen Dank im Voraus für jede Anleitung, die Sie anbieten können.
Sie rufen RTOS() in Ihrem Interrupt auf und die RTOS()-Funktion hat "while (1);" darin (Endlosschleife?)
Ich bin mir nicht sicher, warum Sie die vollständigen Interrupt-Register innerhalb Ihres Interrupts zurücksetzen würden.
Eine Endlosschleife in Ihrem Interrupt führt höchstwahrscheinlich zu einer Fehlfunktion Ihres Programms.
Sehen Sie sich auch den Kommentar von Roger Rowland an: „Wo ist count
definiert? Haben Sie es markiert volatile
? – Roger Rowland vor 15 Minuten“. Dies ist ein ziemlich häufiger Fehler und könnte auch hier der Punkt sein.
volatile
zu Ihrer hinzu int
, also volatile int count;
sehen Sie, ob das einen Unterschied macht, und lesen Sie auf jeden Fall, warum es manchmal notwendig ist .while (1);
in RTOS(), das sich in Ihrem Interrupt befindet. Selbst wenn Sie das Interrupt-Flag zurücksetzen, unterbricht der Interrupt Ihre aktuelle Interrupt-Routine nicht! Es wird also in der Zwischenzeit stecken bleiben. Ich schlage vor, Sie legen das while(1);
in Ihre Hauptdatei oder löschen es vollständig. `while(1){ //some code }' wird oft in main ausgeführt, um das Programm am Laufen zu halten/diesen Code in einer Schleife zu durchlaufen. Aber Sie sollten diese Schleife nicht in einer Interrupt-Service-Routine machen.void timer_isr (void) { INTCONbits.TMR0IF = 0; count = count++; LATD = count; RTOS(); }
Dies ist Ihr Interrupt-Routinencode. Es ruft RTOS()
... und RTOS()
hat eine while(1)
, damit es die Schleife oder ISR (Interrupt Service Routine) nie verlässt. Also ja, der Interrupt passiert nur einmal, wie Sie dachten.while(1);
damit sie kontinuierlich ausgeführt werden. . Um Ihren Code jedoch kontinuierlich auszuführen, while(1);
wird oft in die Hauptdatei gestellt. Obwohl dies das Problem nicht löst. (Solange Sie das CTOS() nicht in Ihrem Interrupt haben. Ich würde vorschlagen, Ihr Programm Schritt für Schritt durchzugehen oder zu prüfen, ob es den Interrupt jemals verlässt.Ich kenne C18 nicht, aber ich benutze seinen Nachfolger XC8.
Weiß der C18-Compiler in Bezug auf Ihre ISR, dass er void low_interrupt (void) ausführen soll, wenn ein Interrupt mit niedriger Priorität generiert wird? Ich habe bestimmte Funktionen für Interrupts bei einigen Compilern gesehen, aber XC8 funktioniert wie folgt:
// HP int declared with 'high_priority' identifier, name function as you see fit
interrupt high_priority void isr_high(void)
// LP int declared with 'low_priority' identifier, name function as you see fit
interrupt low_priority void isr_low(void)
Wenn C18 stattdessen bestimmte Funktionsnamen verwendet, vergewissern Sie sich, dass Sie sie richtig eingegeben haben.
Zweitens, hier ist, wie ich mit Ihrem Timer-Überlauf umgegangen wäre:
interrupt high_priority void isr_high(void)
{
// TIMER0 Overflow
if (INTCONbits.TMR0IF)
{
LATEbits.LE0 ^= 1; // Toggle RE0
INTCONbits.TMR0IF = 0; // Clear the interrupt flag
}
}
Hoffe das hilft.
Danke für all die Hilfe.
Mit ein bisschen Arbeit in MPLabSim habe ich meinen Fehler gefunden und der korrigierte Code unten funktioniert korrekt, zumindest in MPLabSim:
EDIT: Funktioniert jetzt auch auf echter Hardware!!!!
void main (void) /* */
{
TRISA = 0; /* */
TRISC = 0; /* */
TRISB = 0;
TRISD = 0x00;
RTOS();
}
void low_interrupt ()
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interrupt low_interrupt //save =PROD
void timer_isr ()
{
if(INTCONbits.TMR0IF==1)
{
count++;
INTCONbits.TMR0IF = 0;
}
}
void RTOS ()
{
T0CONbits.T08BIT = 0; // 16-bit timer
T0CONbits.T0CS = 0; // increment on instruction cycle input
T0CONbits.T0SE = 0; // increment on low--> high transition of clock
T0CONbits.PSA = 1; // T0 prescaler not assigned i.e. 1:1 prescaler.
RCONbits.IPEN = 1; //Enable Interrupt Priorities
INTCONbits.GIEL = 1; //Enable Low Priority Interrupt
INTCONbits.GIEH = 0; // disable high priority interrupts
INTCONbits.GIE = 1; //Enable Global Interrupts
INTCONbits.TMR0IE = 1; //Enable Timer0 Interrupt
INTCON2bits.TMR0IP = 0; //TMR0 set to low Priority Interrupt
INTCONbits.TMR0IF = 0; // T0 int flag bit cleared before starting
T0CONbits.TMR0ON = 1; // timer0 START
counter(count);
}
void counter ()
{
LATD = count;
}
Roger Rowland
count
definiert? Hast du es markiertvolatile
?Benutzer17592
count++;
stattdessen tuncount = count++;
. Der++
Operator speichert den neuen Wert für Sie.