Forum: Mikrocontroller und Digitale Elektronik PIC16F877 - Interrupt auslösen bei Empfang eines Bytes


von Olaf R. (gruser)


Lesenswert?

Hallo,

ich laboriere im Moment an dem Interrupt meines PIC16F877 herum. Ziel 
ist es in die Interrupt-Routine zu springen, sobald die USART ein Byte 
empfängt. Leider funktioniert es so gar nicht.

Nachstehend der Code meines Testprogramms, im Hauptprogramm klickert 
mein Relais immer hin und her, sobald ich ein Byte an den PIC schicke 
sollte das Relais prompt ausgeschaltet werden (nicht sinnig, soll ja nur 
zum Testen sein).

Kann es sein, dass RB0 den Interrupt auslöst und nicht die USART? Wenn 
ja - wie kann man das ändern?

Gruß
Olaf



#include <C:\cc5\16F877.H>
#include <C:\cc5\int16CXX.H>

// 
Speicherschutz12,13,4,5=aus,Debug11=aus,ProgrammFlash9=an,EEpromRead8=an 
,
// NiedervoltProgr7=aus, NiederVoltReset6=an,EinschaltTimer3=an,
// WachDogTimer2=aus,Oszillator0,1=XC
#pragma config |= 0b.11.111101.11.00.10

//*******  Interrupt  *************************************************

#pragma origin 4

interrupt InterruptRuine(void)
{
int_save_registers
PORTA = 0b.0000.0000;
//PIR1bits.TXIF = 0;
int_restore_registers
}

//********************************************************************** 
********

void InitUSART()
{
    BRGH=1;
//    SPBRG=129;              // (9600 baud @ 20MHz input clock)
    SPBRG=20;              // Änderung!!! (57600 baud @ 20MHz input 
clock)

    SPEN = 1;               // Set_Serial_Pins;
    SYNC = 0;               // Set_Async_Mode;
    TX9 = 0;                // Set_8bit_Tx;
    RX9 = 0;                // Set_8bit_Rx;
    CREN = 1;               // Enable_Rx;
    TXEN = 1;               // Enable_Tx;
    RCIE=1;                 // Rx Interrupt ein!!!
}

//*******  Hauptprogramm 
*************************************************

void main(void)
{
    uns16 a;                // Variablen
    char n;
    char w;
    uns16 addr;
    uns16 test1;
    uns16 test2;

    TRISA = 0b.0000.0000;    // PortA als Ausgang definieren
    TRISB = 0b.0000.0000;    // PortB als Ausgang definieren
    TRISE = 0b.0000.0000;    // PortE als Ausgang definieren
    TRISD = 0b.0000.0000;

    PORTA = 0b.0000.0000;
    PORTB = 0;
    PORTE = 0;
    PORTD = 0b.0000.0000;

    TRISC=0b.1011.1100;     // RC6>TX, RC7>RX
    InitUSART();            // Hardwareschnittstelle des PICs einstellen

  while (1)
    {
    pause(500);
    pause(500);
    pause(500);
    pause(500);
    pause(500);
    pause(500);
      PORTA = 0b.1111.1111;
    pause(500);
    pause(500);
    pause(500);
    pause(500);
    pause(500);
    pause(500);
     PORTA = 0b.0000.0000;
    }
}

von holger (Gast)


Lesenswert?

>interrupt InterruptRuine(void)

Ja deine Routine ist echt ne Ruine ;)

von Olaf R. (gruser)


Lesenswert?

Tja.. der Name ist Programm ;-) Das Ding habe ich abgeschrieben - und 
dann auch noch falsch. Ist das ein feststehender Begriff und hat 
Auswirkungen auf das Programm?

Wenn nein dann bitte nun die konstruktiven Kommentare ;)

von Michael H. (morph1)


Lesenswert?

du musst noch min. GIE = 1 machen eventuell auch PIE = 1

aber ich muss zugeben den 877 hab ich lang nicht mehr verwendet, den 
877A kaum weniger lang nimma =)

aktuell ist der 887 dieser reihe, solltest mal ein sample holen.

von Olaf R. (gruser)


Lesenswert?

Negativ... klappt leider nicht

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Zumindest in Assembler müssen RX und TX auf Eingang gestellt werden. Der 
UART übernimmt dann die richtige Umschaltung auf Ein- und Ausgang sobald 
er eingeschaltet wird. Probier das mal.

Sven

von Olaf R. (gruser)


Lesenswert?

Das Empfangen und Senden klappt ja - das habe ich schon ausprobiert. Nur 
springt das Programm nicht in das Interrupt-Programm :-(

von Meister E. (edson)


Lesenswert?

Hallo Olaf,

um periphere Interrupts zuzulassen, müssen GIE und PEIE in INTCON 
gesetzt sein. Zusätzlich vorher das Enable-Bit des gewünschten Moduls 
(in deinem Fall RCIE) in einem der PIEx-Register setzen.

Des Weiteren macht einiges in deinem Code so keinen Sinn. Hinweis: 
Welches Ereignis soll eigentlich in der ISR behandelt werden - TX oder 
RC Interrupt?

Gruß,
Edson

von Olaf R. (gruser)


Lesenswert?

Hi Edson,

schönen Dank für deinen Tipp. PEIE hatte noch gefehlt, dewegen ist das 
Programm nicht in die Interrupt-Routine gesprungen. Leider springt es im 
Moment allerdings auch nicht mehr heraus, ich denke hier muss noch ein 
Flag per Software herausgenommen werden - da bin ich noch auf der Suche, 
bin aber guter Dinge - oder weißt du das auch?

Ich möchte den Interrupt nutzen um aus dem normalen Programm 
herauszuspringen, wenn ein Byte empfangen wird, es auszulesen, um dann 
wieder im normalen Programm weiterzumachen.

Gruß
Olaf

von Dieter W. (dds5)


Lesenswert?

Das nach einem Receive-Interrupt zu löschende Flag ist das RCIF.

von Michael H. (morph1)


Lesenswert?

witzig, fragt man sich wofür ich das geschrieben hatte =)

von Meister E. (edson)


Lesenswert?

gruser wrote:
>Leider springt es im
>Moment allerdings auch nicht mehr heraus, ich denke hier muss noch ein
>Flag per Software herausgenommen werden - da bin ich noch auf der Suche,
>bin aber guter Dinge - oder weißt du das auch?

Ja, das meinte ich mit dem Hinweis in meinem Beitrag. dds5 hat es dir im 
Detail verraten.

morph1 wrote:
>witzig, fragt man sich wofür ich das geschrieben hatte =)

Naja, wahrscheinlich konnte der gute Olaf deinen Tippfehler (PIE statt 
PEIE) mangels Erfahrung nicht selbst korrigieren.

Gruß,
Edson

von Olaf R. (gruser)


Lesenswert?

... hier sind nur Helden... dankeschön. Der doofe Olaf hats verstanden 
und es klappt sogar. Mir fällt nur auf dass die Variablen in der 
Interrupt-Routine neu definiert werden müssen - insofern kann ich nicht 
ohne weiteres Werte übergeben an mein normales Hauptprogramm. Tja - 
sicher wieder ein typischer Olaf - aber vielleicht helft ihr trotzdem 
noch einmal ;)

von Michael H. (morph1)


Lesenswert?

du machst das ja in C

lies dich mal in das themengebiet der "Globalen Variablen" ein, du 
kriegst die daten damit recht bequem aus der interrupt routine heraus :)

btw, den tippfehler hatte ich glatt nicht bemerkt, tut mir leid :|

von Olaf R. (gruser)


Lesenswert?

Ist ja schon mal gut zu wissen dass es geht, werde mich heute abend mal 
einlesen - konnte mir auch nicht vorstellen dass das ein "No-Go" wäre. 
Die Variablen-Deklarationen wollte ich mir eh noch einmal anschauen.

Gruß
Olaf

von Olaf R. (gruser)


Lesenswert?

Wenn man die Variablendeklaration unter #include... schreibt (und nicht 
in das Hauptprogramm "main") ist sie automatisch eine globale Variable.

Eine Sache ist mir noch aufgefallen, ich kann aus der Interrupt-Routine 
keine Funktion aufrufen. Gibt es da noch einen Trick?

Gruß
Olaf

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.