mikrocontroller.net

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


Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht 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;
    }
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>interrupt InterruptRuine(void)

Ja deine Routine ist echt ne Ruine ;)

Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Michael H. (morph1)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Negativ... klappt leider nicht

Autor: Sven Stefan (stepp64) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Olaf Rechtner (gruser)
Datum:

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

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dieter Werner (dds5)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das nach einem Receive-Interrupt zu löschende Flag ist das RCIF.

Autor: Michael H. (morph1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
witzig, fragt man sich wofür ich das geschrieben hatte =)

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Michael H. (morph1)
Datum:

Bewertung
0 lesenswert
nicht 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 :|

Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Olaf Rechtner (gruser)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.