Forum: Mikrocontroller und Digitale Elektronik PIC18F46K80 CAN ISR


von Hans (Gast)


Lesenswert?

Guten Tag und ein schönes Wochenende an alle Leser und Beantworter,

ich sitze seit einigen Tagen an einer CAN-Kommunikation mittels PIC 
18F46K80. Senden, Empfangen, klappt alles wunderbar - nur an der ISR 
scheitere ich. Ich nutze MPLABX und einen XC8-Compiler. Eigentlich ist 
mit dieser Kombination die Erstellung der ISR fast trivial. Nur für mich 
irgendwie nicht.

Den globalen Interrupt habe ich freigegeben, den Peripherial genauso, 
nur in die ISR will er einfach nicht - hat jemand auf die Schnelle eine 
Idee wo mein Fehler liegt?

Vielen Dank im Voraus für alle die eine passende Antwort parat haben.
1
// PIC18F46K80 Configuration Bit Settings
2
3
// 'C' source line config statements
4
5
#include "configuration.c"
6
#include <xc.h>
7
#include "p18f46k80.h"
8
9
//Funktionsprototypen
10
void delay();
11
void InitECAN();
12
void ECAN_Transmit();
13
void interrupt ISR(void);
14
15
void delay() {
16
    int counter = 0;
17
    for (counter = 0; counter<10000; counter++) {
18
        ;
19
    }
20
}
21
22
void main(void) {
23
24
    TRISBbits.TRISB2 = 0;
25
    TRISBbits.TRISB3 = 1;
26
    TRISCbits.TRISC6 = 0;
27
    TRISCbits.TRISC7 = 1;
28
    TRISBbits.TRISB5 = 0;
29
30
    InitECAN();
31
    INTCONbits.GIE = 1;
32
    PIE5bits.RXBnIE = 1;
33
    PIE5bits.IRXIE = 1;
34
    RXB0IF = 0;
35
    RXB1IF = 0;
36
    IRXIF = 0;
37
38
    while (1) {
39
        PORTBbits.RB0 = 0;
40
        delay();
41
        PORTBbits.RB0 = 1;
42
        delay();
43
}
44
45
}
46
47
void interrupt ISR(void)
48
{
49
    if(RXB0IF && PIE5bits.RXBnIE)
50
    {
51
        RXB0IF = 0;
52
        ECAN_Transmit();
53
    }
54
}

von Erich (Gast)


Lesenswert?

Dein Programm kann niemals so funktionieren oder funktioniert haben.
Egal mit mit oder ohne Interrupt.

"RXBnIE"  haha

Gruss

von Stephan M. (multimeter90)


Lesenswert?

Ich weiß nicht wie es mit dem xc8 aussieht. Ich benutze den C18. Da 
musste der ISR immer noch ein #pragma davor um dem Compiler zu sagen, wo 
die Funktion (im Speziellen _asm GOTO ISR _endasm) liegen soll, 
Ausschnitt:

1
#pragma code high_vector=0x08
2
void HightInterrupt(void) { _asm GOTO ISR _endasm }
3
#pragma code
4
5
#pragma code low_vector=0x18
6
void LowInterrupt(void) { _asm GOTO ISR _endasm }
7
#pragma code
8
9
10
volatile uint32_t os_SysTime = 0;
11
12
13
/**
14
 * @brief Interrupt-Service-Routine des Controllers
15
 *
16
 */
17
#pragma interruptlow ISR
18
void ISR(void) {
19
20
}

von Chris B. (dekatz)


Lesenswert?

Ich weiss nicht was nach einem POR in den Registern steht, sehe jetzt 
auch nicht nach....
Aber vor der globale Interrupt Freigabe:
Mit RCON.IPEN festlegen ob mit oder ohne priorisierten Interrupt 
gearbeitet wird
Im IPRn Register festlegene ob HIGH oder LOW Interrupt.
Und sicherheitshalber die entsprechenden Flags im PIRn Register löschen.

von Hans (Gast)


Lesenswert?

@Erich: Interessant, dass dein Post nur den Sinn hatte mich auszulachen! 
Mal den Befehl im MPLABX mit XC8 eingegeben? Der Comnpiler unterstützt 
diesen Befehl, aber kein Problem, nicht alle Menschen haben Interesse 
daran sich weiterzubilden - und doch, der Rest hat funktioniert!! Egal 
was du glauben magst.

@Stephan Meter: ja, so kenne ich die Routine auch noch als ich sie noch 
im alten MPLAB mit C18 geschrieben habe. Auf dieser Seite:
http://microchip.wikidot.com/faq:31
wird die Implementierung beschrieben wie sie eigentlich in XC8 
vorgesehen ist. Trotzdem vielen Dank für deine Bemühungen.

@Chris B: vielen Dank für den Tipp, werde morgen nochmal schauen ob es 
daran gelegen hat, jetzt ist eindeutig schon zu spät :) hab' gerade auch 
nochmal in das DB geschaut und auf S.147 wieder das gefunden bei dem ich 
mir sicher war, dass ich es schon mal gelesen hatte.

"When the IPEN bit is cleared (default state), the interrupt priority 
feature is disabled and interrupts are compatible with PIC® mid-range 
devices. In Compatibility mode, the
interrupt priority bits for each source have no effect."

Was ich gerade allerdings auch noch gelesen habe, ist, dass das PEIE-Bit 
im INTCON-Register gesetzt werden muss. Das habe ich vergessen.

Lösung kommt, wenn ich sie habe. Wenn natürlich jemand schneller drauf 
kommt - VIELEN Dank

von Hans (Gast)


Lesenswert?

Auch wenn es Ignoranten wie Erich niemals glauben werden (ich hoffe 
nicht, dass ich niemals mit solchen Menschen zusammenarbeiten muss) - 
hier der funktionierende CAN-Quellcode. Geschrieben für MPLAB X mit 
XC8-Kompiler. Vielleicht hilft es jemandem weiter der im Rahmen seines 
Studiums (so wie ich) oder sonstwie damit zu tun hat. Ich wäre froh 
gewesen in diesem Forum etwas dergleichen zu finden, statt ausgelacht zu 
werden!! Gibt es hier keine Moderatoren die so einen Mist unterbinden?
1
// PIC18F46K80 Configuration Bit Settings
2
3
// 'C' source line config statements
4
5
#include "configuration.c"
6
#include <xc.h>
7
#include "p18f46k80.h"
8
9
//Funktionsprototypen
10
void delay();
11
void InitECAN();
12
void ECAN_Transmit(BYTE);
13
unsigned char ECAN_Receive();
14
15
void interrupt ISR(void)            // Interrupt-Service-Routine
16
{
17
    if(RXB1IF && PIE5bits.RXBnIE)   // bei Auslösen des CAN-Empfangen-Interrupts
18
    {
19
        RXB1IF = 0;                 // Interrupt-Flag zurücksetzen
20
        ECAN_Receive();             // Nachricht lesen
21
        ECAN_Transmit(0x02);        // Nachricht versenden
22
    }
23
}
24
25
void delay() {                      // Rudimentäre Warteschleife
26
    int counter = 0;                // Zähler=0 setzen
27
    for (counter = 0; counter<10000; counter++)
28
    {
29
        ;
30
    }
31
}
32
33
void main(void) {
34
35
    TRISBbits.TRISB2 = 0;           // RB2 als Output
36
    TRISBbits.TRISB3 = 1;           // RB3 als Input
37
    TRISCbits.TRISC6 = 0;           // RC6 als Output
38
    TRISCbits.TRISC7 = 1;           // RC7 als Input
39
40
    InitECAN();                     // Inititialisieren des ECAN-Moduls
41
    RXB0IF = 0;                     // Interrupt-Flag löschen
42
    RXB1IF = 0;                     // Interrupt-Flag löschen
43
44
    INTCONbits.GIE = 1;             // Global Interrupts freigeben
45
    INTCONbits.PEIE = 1;            // Peripheral Interrupts freigeben
46
    PIE5bits.RXBnIE = 1;            // CAN-Receive-Interrupts freigeben
47
48
    while (1) {                     // while-Schleife für Hauptprogramm
49
        PORTBbits.RB0 = 0;          // Blinkende LED zur Funktionsanzeige
50
        delay();
51
        PORTBbits.RB0 = 1;
52
        delay();
53
    }
54
}

von Stephan M. (multimeter90)


Lesenswert?

Woran lag es denn nun genau? Also die IS-Routine sieht ja gleich aus. 
Was hat jetzt den Erfolg gebracht?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.