Schönen Abend, ich beschäftige mich eher seit kurzer Zeit mit der Kunst des uC-Programmierens und habe eine für viele von euch wahrscheinlich eher dumm gestrickte Frage. Hier mein Problem: Ich würde gerne innerhalb des Hauptprogramms durch eine while-Schleife das Programm zum Warten veranlassen. Dieses Warten soll unterbrochen werden, wenn eine der beiden Bedingungen erfüllt ist: 1.) die Variable "start" ihren Wert auf 1 verändert (dies kann nur innerhalb der Interrupt-Routine geschehen) 2.) der Zustand eines als Eingang definierten Pins auf logisch "high" wechselt. Der Code gestaltet sich folgendermaßen (so wie ich's mir ersponnen habe): SIGNAL(SIG_INTERRUPT0) { if (start == 0) { start = 1; ... } else { start = 0; ... } } // im Main: volatile uint8_t start; while( !(PINC & (1<<PC1)) || (start) ); <- hier das Problem Die Einzelanweisung funktionieren einwandfrei, sprich die Abfrage des Pins PC1 oder die Abfrage nach dem Variablenwert start. Lediglich die mit Oder (||) verknüpfte Symbiose möchte irgendwie nicht funken?? Nun habe ich das Tutorial durchforstet (wirklich gut gemacht!) aber in meinem Fall glaube ich liegt das Problem eher bei meinem C-Code. ich habe auch schon diverse andere Codes versucht wie z.B.: while( !(PINC & (1<<PC1)) || (start==1) ); Langsam weiß ich nicht recht weiter. Ich hoffe irgend jemand kann mir hierbei helfen. Gruß, Pawel
Hallo Rufus, danke für die schnelle Antwort. Ist die Deklaration denn falsch ? volatile uint8_t start; Oder ist es die Position der Deklaration im allgemeinen Teil des Programms (also unmittelbar vor dem Main-Hauptprogramm, aber in der gleichen C-Datei)
Ja, wenn "volatile uint8_t start;" in dem main-rumpf steht, ist diese Variable auch nur dort sichtbar.
Hi Pawel Nee, die Deklaration mit volatile ist prima! Das Problem liegt woanders, Du hast einen Logik-Fehler: In Deinem Fall brauchst Du eine AND-Verknüpfung nicht OR. while( !(PINC & (1<<PC1)) && (start==1)); Du wirst bestimmt selbst draufkommen, wieso... ;o)) Gruss Peter
Hallo Peter, du hattest vollkommen recht. Die Logik war's. Ich danke dir für die gute Antwort zu so später Stund. Gruß, Pawel
Zu der Logik: Als Eingang stehen der Pin und der Inhalt von start zur verfügung. Der Pin sei durch P repräsentiert und start durch C (start=0 sei logisch 0, alles andere logisch 1). Soll der Abbruch erfolgen, wenn mindestens eine der beiden Bedingungen erfüllt ist, so muss gelten: Abbruch A = P + C. Die Schleifenbedingung S der while-Schleife ist der Abbruchbedingung entgegengesetzt, also S = /A. Somit wird S = /(P + C). Nun kann man noch mit DeMorgan rumröteln und S = /P * /C abfragen. Belassen wir es mal beim ersteren. while(S) while(/A) while(/(P + C)) while(!(P + C)) while(!((P) + start)) while(!((PINC & (1 << PC1)) + start)) Eingesetzt in dem Sourcecode int main (void) { while(!((PINC & (1 << PC1)) || start)) ; while(!(PINC & (1 << PC1)) && (start == 1)); } führt es zu folgendem Assembler-Code: ... while(!((PINC & (1 << PC1)) || start)) ; 7c: 99 99 sbic 0x13, 1 ; 19 7e: 04 c0 rjmp .+8 ; 0x88 80: 80 91 60 00 lds r24, 0x0060 84: 88 23 and r24, r24 86: d1 f3 breq .-12 ; 0x7c while(!(PINC & (1 << PC1)) && (start == 1)); 88: 99 99 sbic 0x13, 1 ; 19 8a: 04 c0 rjmp .+8 ; 0x94 8c: 80 91 60 00 lds r24, 0x0060 90: 81 30 cpi r24, 0x01 ; 1 92: d1 f3 breq .-12 ; 0x88 ... start steht im RAM bei 0x0060. Der Vergleich mit der zuvor genannten Lösung zeigt einen Unterschied auf. Im ersten Fall wird in der Schleife verblieben, wenn start==0 ist. Dagegen im zweiten Fall, wenn start==1 ist. Gruß Marco -
@Pawel: Bitte, gern geschen. Aber Pawel hat eigentlich mit seinem Hinweis ebenfalls recht: "volatile uint8_t start;" müsste ausserhalb vom main als globale Variable definiert sein. Reklamiert denn der Compiler nicht, weil "start" in der ISR undefiniert ist? @Marco: Nette Abhandlung, Du magste es offenbar sehr ausführlich! ;o)) Trotzdem hast Du nicht ganz recht: Im ersten Fall wird in der Schleife verblieben, solange mindestens eine der zwei Bedingungen True ist: (PINC.1=High) und/oder (Start!=0) Im zwitenFall wird in der Schleife verblieben, solange beide Bedingungen True sind: (PINC.1=High) und (Start==1) Gruss Peter
Erst mal frohe Weihnachten! @Peter In der Tat weicht meine Lösung von der Aufgabenstellung ab. Dort steht: ...Warten soll unterbrochen werden, wenn eine der beiden Bedingungen erfüllt ist: ... Wenn wirklich nur eine der beiden Bedingungen zum Ausbruch aus der Schleife führen sollte, so müsste wohl irgendwie eine XOR-Verknüfung eingebaut sein. Zweitens sollte das Warten unterbrochen werden, wenn start auf 1 geht. Hier sehe ich den Fehler, denn es müsste (Start == 0) im zweiten Fall heißen. Und wenn man sich den Assembler-Code ansieht, sieht man, dass beide Routinen fast gleich sind. Im ersten Fall wird in der Warteroutine verblieben bei Start==0 (and r24, r24) im zweiten Fall bei Start==1 (cpi r24,0x01). Bei Beiden Routinen kann ein gesetzter Portpin zum rjmp +8 Befehl führen, wo dann die zweite Bedingung übergangen wird. Gruß Marco -
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.