PIC18 High Priority Interrupt unterbricht nicht den Low (xc8)

Ich habe versucht, die Prioritätseigenschaft von Interrupts auf PIC18F46K22 uC zu lernen und zu implementieren. Ich benutze MPLABX und XC8-Compiler.

In meinem Code (transformiert aus einem Beispielcode) habe ich einen externen Interrupt (INT1) und einen USART-Empfangsinterrrupt (RC1IF). Der externe Eingang ist ein LED-Treiber und USART ist ein einfaches Echoprogramm, das von einem PC-Terminal gesteuert wird.

Einige Teile des Codes werden unten mit Kommentaren bereitgestellt. Code wird erfolgreich erstellt. Aber mit dieser "High-Low" -Kombination kann ich, wenn USART aktiv ist und das Programm erfolgreich Text an das Terminal zurückgibt, die Übertragung nicht mit einem externen Interrupt unterbrechen, der durch eine Drucktaste gegeben wurde.

Hier sind ISRs.

void interrupt low_priority USB(void)
{

if (PIR1bits.RC1IF==1)  // check if receive interrupt has fired
{
    t = RCREG1;      // read received character to buffer


    // check if received character is not new line character
    // and that maximum string length has not been reached
    if ( (t != '\n') && (rcindex < STRLEN) )
    {
        rcbuf[rcindex] = t; // append received character to string
        rcindex++;          // increment string index
    }
    else
    {
        rcindex = 0;         // reset string index
        USART_puts(rcbuf);  // echo received string


        for(int x=0; x<STRLEN+1; x++){ //clear
                rcbuf[x] = 0;           // any leftover
            }                           // from
        RCREG1 = 0x00;                  // last
        TXREG1 = 0x00;                  // transmission
    }

    PIR1bits.RCIF = 0;      // reset receive interrupt flag
}
}

Und

void interrupt high_priority inticik(void)
{
if(INTCON3bits.INT2IF==1)
{
    LATAbits.LA1 = ~LATAbits.LA1;
    __delay_ms(20);
}

INTCON3bits.INT2IF = 0;
}

Dies ist die Interrupt-Konfigurationsfunktion;

void interrupt_config(void)
{
 //interrupt main configuration
RCONbits.IPEN = 1;        // interrupt priority mode enabled, H or L interrupts
INTCONbits.GIE_GIEH = 1;  // high priority interrupts are enabled
INTCONbits.PEIE_GIEL = 1; // low priority interrupts are enabled

//pin interrupt 1&2 enable + priority assignments + edge selection
TRISBbits.TRISB2 = 1;
ANSELBbits.ANSB2 = 0;
INTCON3bits.INT1IE = 1; // int1 is enabled
INTCON3bits.INT2IE = 1; // int2 is enabled
INTCON3bits.INT1IP = 1; // int1 is high priority
INTCON3bits.INT2IP = 1; // int2 is high priority
INTCON2bits.INTEDG1 = 1;  // rising edge
INTCON2bits.INTEDG2 = 1;  // rising edge

//EUSART interrupt enable + priority assignments

PIE1bits.RC1IE = 1; //receive interrupt enabled
PIE1bits.TX1IE = 1; //transmit interrupt enabled
IPR1bits.RC1IP = 0; // receive is low priority
IPR1bits.TX1IP = 0; // transmit is low priority
}

Und hier ist die Hauptfunktion.

int main(void)
{
TRISAbits.TRISA1 = 0;
LATA = 0x00;
interrupt_config();

USART_init();

USART_puts("Init complete!\n");

//main loop
while(1)
{
    Sleep();
}

return 0;
}

Andere Teile des Codes wie USART-Funktionen und "config.h" conf. Bitleisten sind wegen Irrelevanz nicht vorgesehen.

Danke schön.

Bearbeiten

Ich habe vergessen zu erwähnen, wenn ich die ändere,

"void interrupt low_priority USB(void)"

Aussage zu

"void interrupt high_priority USB(void)"

Programm funktioniert erfolgreich und echot auf dem Terminal. Aber wenn es als "low_priority" eingestellt ist, funktioniert das USART-Modul nicht auf dem Terminal. Nur der externe Interrupt wird erfolgreich ausgeführt.

Ungeachtet der Antwort auf Ihre (gute) Frage sollten Sie eine Unterbrechung nicht hinauszögern. Setzen Sie ein Flag und verzögern Sie es an anderer Stelle im Hauptprogramm.
Verwendest du INT1 oder INT2? Der Intro-Text sagt INT1, der Code initialisiert beide und der Interrupt verwendet INT2.
Sowohl INT1- als auch INT2-Pins haben auch einen Komparator, den ich nicht sehe, wenn Sie ihn deaktivieren. Alle analogen Funktionen müssen deaktiviert werden, um einen Pin als digitalen Eingang zu verwenden.
Danke für den Kommentar. Ich verwende INT1 für meinen Zweck, INT2 war nur für weitere Anwendungen da, ich werde es deaktivieren und es jetzt erneut versuchen. Ich nehme auch an, dass Sie das Löschen von ANSELB-Registerbits durch Deaktivieren der analogen Funktionen erwähnt haben, oder irre ich mich? Bei der Definition von ANSELB reg. heißt es im Datenblatt "digitaler Eingangspuffer ist aktiviert". Oder gibt es noch etwas zu ändern?

Antworten (1)

Obwohl ich nicht sicher bin, warum, hat dies mein Problem gelöst.

Aus dem PIC18F46K22-Datenblatt

Beim Power-On-Reset wird das ADON-Bit gelöscht, was bedeutet, dass es den A/D-Wandler standardmäßig deaktiviert, richtig? Das bedeutet, ob ich den A/D-Wandler deaktiviere oder nicht, er wird automatisch deaktiviert.

ADCON0bits.ADON = 0;

Aber ich habe diese Zeile zu meiner Konfiguration hinzugefügt und es hat funktioniert, jetzt funktionieren sowohl der externe Interrupt (hohe Priorität) als auch der USART-Interrupt (niedrige Priorität) im selben Programm.

Es ist eine Lösung, aber ich frage mich immer noch, warum es funktioniert hat.