Forum: Mikrocontroller und Digitale Elektronik RB0 als externe Interrupt-"Quelle"


von bemyguest (Gast)


Lesenswert?

Hallo,

ich hab nen PIC18F mit einem FPGA verbunden und möchte das der FPGA 
einen Interrupt im PIC auslösen kann. Dafür möchte ich RB0 verwenden. 
Leider klappt das nicht (blutiger Anfänger :/). Mein C-Code:
1
main()
2
3
{
4
  
5
   char command, shift;
6
  
7
   Init_Hardware(); //setzt bestimmte Portbits 
8
   delay_s(3); //zusätzlich eingeführt um sicher zu stellen das alle       
9
               //Betriebsspannungen aufgebaut sind 
10
   trisb.0=0;
11
   trisb.2=0; 
12
   
13
   //Interrupt an RB0 erlauben (fallende Flanke)
14
   intcon.GIE=1;       // Interrupts erlauben
15
   intcon.INT0IE=1;          // Interrupt von RB0 erlauben.
16
   intcon2.INTEDG0=0;        // Fallende Flanke am RB0
17
18
   while(1)
19
   {
20
   .
21
   .
22
   .
23
   }
24
}
25
26
void interrupt()
27
{
28
  if (intcon.RBIF==1) //Flag-Abfrage
29
  {
30
    intcon.RBIF=0; //Lösche Flagbit
31
    trisb.2=0; 
32
    portb.1=1; //Testausgabe ob Interrupt aufgerufen wurde
33
    delay_s(1); 
34
    portb.2=0;   
35
    delay_s(1);
36
  }
37
  
38
  intcon.GIE = 1; //Interrupts wieder erlauben
39
}

Der FPGA is einfach so programmiert, das er bei einem Reset RB0 auf 0 
zieht, ansonsten immer 1.
Was ich realisieren möchte ist, das der PIC aus der while(1)-Schleife 
rausspringt, sobald er das Signal vom FPGA bekommt und kurzfristig etwas 
wichtige Befehle abarbeitet...
Was hab ich vergessen, was mach ich falsch? hoffentlich nicht alles...

Pls help!

von bemyguest (Gast)


Lesenswert?

habe den Code noch einmal editiert, funzt leider immer noch nicht...
1
main()
2
{
3
  //Init_Hardware();
4
  porta.4=1;
5
  delay_s(3);        
6
        trisb.0=1;    //RB0=Input
7
        trisb.2=0;              //RB2=Output //toggle led to indicate  
8
                                //interrupt.
9
  inter_ini();
10
11
  while(1)
12
  {
13
  }
14
15
}         
16
        
17
void interrupt()
18
{  
19
  intcon.INT0IF=0; //clear flag
20
  delay_s(2);
21
  portb.2=1;
22
  delay_s(2);
23
}
24
               
25
               
26
               
27
void inter_ini()
28
{
29
  intcon.INT0IE=1; //enable external interrupt 1 on B0.
30
  intcon.INT0IF=0; //clear external interrupt flag.
31
  intcon2.RBPU=1; //turn off pull-ups
32
  intcon.PEIE=0; //peripheral enable bit set false
33
  intcon.INT0IE=0; //active on falling edge
34
  intcon.GIE=1; //global interrupt enable on
35
}

wieso springt der Interrupt nicht auf einen Flankenwechsel an RB0 an???

von PIC N. (eigo) Benutzerseite


Lesenswert?

Hi,
schau Dir mal das hier an:
http://pic-projekte.de/pic_c.html#intpic

Du musst eine richtige ISR einleiten. Einfach eine Funktion als 
INTERRUPT zu benennen funktioniert so leider nicht. Schau dir den Link 
mal an, mal sehen ob es Dir weiterhilft.

Nabend

von PIC N. (eigo) Benutzerseite


Lesenswert?

Nachtrag: Außerdem schau mal:
1
void inter_ini()
2
{
3
> intcon.INT0IE=1; //enable external interrupt 1 on B0.
4
  intcon.INT0IF=0; //clear external interrupt flag.
5
  intcon2.RBPU=1; //turn off pull-ups
6
  intcon.PEIE=0; //peripheral enable bit set false
7
> intcon.INT0IE=0; //active on falling edge
8
  intcon.GIE=1; //global interrupt enable on
9
}

Bei dem zweiten suchst Du wahrscheinlich dieses hier: INTEDG0

von bemyguest (Gast)


Lesenswert?

ok die Intcon-Register-settings waren nicht 100% korrekt, diese habe ich 
jetzt berichtigt.

Allerdings verstehe ich immer noch nicht wie ich den Interrupt jetzt 
genau initialisiere. Ich benötige also eine pragma-Direktive in der ich 
dem Compiler mitteile an welche Adresse bzw. in welche Routine (die an 
angegebener Adresse sich befindet) er bei einem Interrupt springen soll, 
soweit so gut.

Allerdings sind alle Direktiven die ich bisher im Netz gefunden habe 
nicht mit meinem Compiler kompatibel. Ich benutze Sourceboost und habe 
weder in der Hilfe noch in der PIC18F4520.h-Datei eine Direktive 
gefunden die sich auf eine Interrupt-Initialisierung bezieht. Kennt sich 
hier jemand mit Sourceboost in Verbindung mit der 18F-Familie aus?!

Ich möchte definiv keine if- oder while-Schleife verwenden in der ich 
das Intcon-Interrupt-Flag abfrage, sondern eine richtige 
Interrupt-Routine, welche bei auftreten eines Interrupts (Flankenwechsel 
an RB0) direkt das main()-prog verlässt und in Interruptroutine springt.

Please help :)

von heinzhorst (Gast)


Lesenswert?

Der 18F4520 hat einen Silicon-Bug beim Aufruf der ISR. Muss man mit 
einem kleichen Workarround fixen. Bin ich vor kurzen auch drauf 
reingefallen, allerdings mit dem Timer0-Interrupt. Allerdings hab ich 
noch nie was von Sourcebost gehört. Ich poste mal meinen ISR-Code für 
den MCC18, vielleicht hilft dir das ja weiter.
1
//  interrupt service routine
2
3
#pragma interruptlow LowISR
4
void LowISR(void){
5
6
  //  add low priority interrupt handlers here    
7
8
  TickUpdate();  // Timer0 ISR
9
10
}
11
12
13
#pragma interrupt HighISR
14
void HighISR(void){
15
16
  //  add high priority interrupt handlers here
17
18
  uart_isr();
19
  
20
}
21
22
23
#pragma code LowVector=0x18
24
void LowVector(void){_asm goto LowISR _endasm}
25
#pragma code HighVector=0x08
26
void HighVector(void){_asm goto HighISR _endasm}
27
#pragma code // Return to default code section
28
29
30
//  main
31
32
33
void main(void){
34
35
// initialisation
36
37
RCONbits.IPEN = 1;
38
39
TickInit();
40
41
42
//  enable global interrupt
43
INTCONbits.GIEL = 1;
44
INTCONbits.GIEH = 1;
45
46
uart_puts_rom("Hello world!");
47
48
while(1){
49
50
  // main loop
51
}

so, dazu noch die Initialisierung des Timers:
1
void TickInit(void)
2
{
3
4
  // Use Timer0 for 8 bit processors
5
    // Initialize the time
6
    TMR0H = 0;
7
    TMR0L = 0;
8
9
  // Set up the timer interrupt
10
INTCON2bits.TMR0IP = 0;    // Low priority
11
    INTCONbits.TMR0IF = 0;
12
    INTCONbits.TMR0IE = 1;    // Enable interrupt
13
14
    // Timer0 on, 16-bit, internal timer, 1:256 prescalar
15
    T0CON = 0x87;
16
17
18
}

von bemyguest (Gast)


Lesenswert?

Danke!

allerdings bekomme ich auch hier die Meldung: Unknown or Invalid Pragma 
für #pragma interrupt HighISR und #pragma code LowVector=0x18.


Welchen Compiler könnt ihr den empfehlen, evtl ist Sourceboost auch 
einfach murks...wenns geht freeware...

THX!

von Lehrmann M. (ubimbo)


Lesenswert?

bemyguest schrieb:
> Danke!
>
> allerdings bekomme ich auch hier die Meldung: Unknown or Invalid Pragma
> für #pragma interrupt HighISR und #pragma code LowVector=0x18.
>
>
> Welchen Compiler könnt ihr den empfehlen, evtl ist Sourceboost auch
> einfach murks...wenns geht freeware...
>
> THX!

Das ist ein Code für MPLAB und den entsprechenden C18 Compiler den es 
kostenlos von Microchip gibt.

http://pic-projekte.de/pic_c.html

Da geht's los.

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.