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; } }
>interrupt InterruptRuine(void)
Ja deine Routine ist echt ne Ruine ;)
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 ;)
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.
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
Das Empfangen und Senden klappt ja - das habe ich schon ausprobiert. Nur springt das Programm nicht in das Interrupt-Programm :-(
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
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
Das nach einem Receive-Interrupt zu löschende Flag ist das RCIF.
witzig, fragt man sich wofür ich das geschrieben hatte =)
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
... 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 ;)
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 :|
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.