Programm auf XC866 reagiert sehr seltsam...
-
Hallo zusammen,
ich habe folgende Ausgangssituation: Ein Microcontroller vom Typ XC866 kriegt von einem Rechner mit W2k Prof. über eine 8-Bit-Anbindung insgesamt 5 Byte geschickt. Wenn der Rechner ein Byte angelegt hat gibt er eine positive Flanke an einen Trigger-Eingang des Controllers, auf die dieser mit einem Interrupt - und entsprechender Routine - reagiert.
Diese sieht wie folgt aus:void TriggerISR() interrupt 9 { IRCON0 &= 0xf7; //reset IR-Bit of trigger switch (counter) { case 0: time1 = P3_DATA; //get LSB of time if (time1 == 0) { P0_DATA &= 0xf8; P0_DATA |= 1; } else { if (time1 == 2) { P0_DATA &= 0xf8; P0_DATA |= 2; } } counter = 1; break; case 1: time2 = P3_DATA; //get 2nd byte of time if (time2 == 0) { P0_DATA &= 0xf8; P0_DATA |= 0x3; } else { if (time2 == 1) { P0_DATA &= 0xf8; P0_DATA |= 0x4; } } counter = 2; break; case 2: time3 = P3_DATA; //get MSB of time if (time3 == 0) { P0_DATA &= 0xf8; P0_DATA |= 0x5; } else { if (time3 == 13) { P0_DATA &= 0xf8; P0_DATA |= 0x7; } } counter = 3; break; case 3: phase = P3_DATA; //get phase information if (phase == 0) { P0_DATA &= 0xf8; P0_DATA |= 0x6; } else { if (phase == 128) { P0_DATA &= 0xf8; P0_DATA |= 0x1; } counter = 4; break; case 4: if ((P3_DATA & 0x1) == 0) //decide whether phase information is relevant { usePhase = 0; //-> phase ignored } else { usePhase = 1; //-> phase important } if ((P3_DATA & 0x2) == 0) //decide which contactor is used for shoot { mainc = 0; //serial contactors are used } else { mainc = 1; //main contactor is used } counter = 5; break; } }
Die Ausgaben an Port0 (P0_DATA) sind nur dazu da, dass ich an angeschlossenen LED's erkennen kann, wo im Programm er gerade steckt (debuggen geht leider nicht).
Jetzt das Problem: Schickt das Programm eine Kombination an Bytes, die in den if-else-Zweigen abgefragt wird (also z.B. 0x0000100), dann gehen die LED's entsprechend an und alles ist wunderbar. Wenn das Programm aber eine Kombination schickt, die nicht in den Abfrage vorkommt läuft er über den break hinaus (vermute ich mal) und macht gleich noch den nächsten case auch mit. Dadurch kommt er natürlich total durcheinander und schiebt vollkommen falsche Zahlen in die Variablen, was mein anschließendes Programm falsch ablaufen lässt.
Wieso macht er das? Ich habe auch schon versucht bei dem zweiten If in jedem case ein else zu machen, bei dem er aus der kompletten ISR aussteigt, aber mit dem gleichen Ergebnis.
Hat jemand eine Idee, was das sein könnte, bin mittlerweile schon ziemlich verzweifelt!Danke fürs lesen und viele Grüße
-
Action schrieb:
Wenn das Programm aber eine Kombination schickt, die nicht in den Abfrage vorkommt.....
dafür gibt es im switch-konstrukt doch die default-alternative...
switch(var) { case 1 : break; case 2 : break; default : break; //hat var einen von 1 und 2 verschiedenen wert, wird default executed }
-
Hallo curry-king,
das Problem ist nicht, dass counter einen Wert hat, der nicht im Switch vorkommt. Das wäre mit dem default kein Problem.
Das Problem ist:
Schicke ich z.B.
1. Byte = 0
2. Byte = 1
3. Byte = 13
4. Byte = 0
5. Byte = 2geht alles gut (weil alle Bytes in den If-Else-Zweigen abgefragt werden)
Schicke ich aber z.B.:
1. Byte = 1
2. Byte = 2
3. Byte, 4. Byte, 5. Byte egal wasgeht es schief, weil er vom case 1 gleich in den case 2 läuft. Das meinte ich mit Kombinationen, die nicht in der Abfrage vorkommt.
Woran kann das liegen?Viele Grüße
-
Du solltest im Fehlerfall (anderer Wert als erwartet) den Counter auf 0 setzen. Das geht entweder mit 'if...else if...else' oder mit 'switch...case...default'
-
Hallo zusammen,
okay, nochmal anders ausgedrückt:
Die if-else-Abfrage sind nur im Moment in dem Programm drin, damit ich erkennen kann (wenn das Programm aus dem Flash des Controllers läuft-->kein Debuggen möglich!), wo er gerade mit der Abarbeitung ist. Die kommen später wieder raus!
Und es ist ja kein Fehlerfall, wenn ich eine Bytekombination übertrage, die nicht in den Abfragen drin ist, das Programm soll natürlich auch auf andere Werte reagieren (sprich, diese in die Variablen time1, time2, time3 und phase schreiben).
Was mich eben nur total verwirrt ist, dass das Programm auf die übermittelten Werte (siehe meine 1. Antwort an curry-king) unterschiedlich reagiert, weil eigentlich sollte er ja nur den Wert in die Variable schreiben und dann Dioden anschalten oder eben nicht.
Warum läuft er von case 1: direkt in case 2:???
-
liegt es vielleicht daran, das du nach jedem case-durchlauf den wert des nächsten
case-zweigs in der variablen counter speicherst?
-
Hallo curry-king,
das muss ich doch machen, damit er beim nächsten Interrupt in den nächsten case-Zweig geht. Meiner Meinung geht er aber eben nicht erst beim nächsten Interrupt in den case 2 sondern gleich nachdem er den case 1 abgearbeitet hat (zumindest wenn ich Werte übermittle, die nicht in den if-else-Blöcken abgefragt werden).
Am Anfang habe ich es anders gemacht. Da habe ich nach dem kompletten switch den Befehl counter++ gehabt. Das hat aber auch nicht funktioniert.
-
werf doch mal deinen debugger an, geh im single-step modus durch den code und
schau, ob er bis zum break kommt.
-
das sagst du so einfach...
Das Programm habe ich mit Keil µVision3 geschrieben. Leider kann ich mit dem Tool aber nicht debuggen (um das zu können bräuchte ich nen extra Adapter für mein Kit und der ist nicht so ganz billig - wenn ich mich recht erinnere so ca. 300€)...
Deswegen habe ich mir ja die Dioden zur Hilfe genommen, damit ich sehe, wo er ist.
Viele Grüße
-
Versuch's mal so:
void TriggerISR() interrupt 9 { IRCON0 &= 0xf7; //reset IR-Bit of trigger switch (counter) { case 0: counter = 1; time1 = P3_DATA; //get LSB of time if (time1 == 0) { P0_DATA &= 0xf8; P0_DATA |= 1; } else if (time1 == 2) { P0_DATA &= 0xf8; P0_DATA |= 2; } else counter = 0; break; case 1: counter = 2; time2 = P3_DATA; //get 2nd byte of time if (time2 == 0) { P0_DATA &= 0xf8; P0_DATA |= 0x3; } else if (time2 == 1) { P0_DATA &= 0xf8; P0_DATA |= 0x4; } else counter = 0; break; case 2: counter = 3; time3 = P3_DATA; //get MSB of time if (time3 == 0) { P0_DATA &= 0xf8; P0_DATA |= 0x5; } else if (time3 == 13) { P0_DATA &= 0xf8; P0_DATA |= 0x7; } else counter = 0; break; case 3: counter = 4; phase = P3_DATA; //get phase information if (phase == 0) { P0_DATA &= 0xf8; P0_DATA |= 0x6; } else if (phase == 128) { P0_DATA &= 0xf8; P0_DATA |= 0x1; } else counter = 0; break; case 4: counter = 5; usePhase = 1; mainc = 1; if ((P3_DATA & 0x1) == 0) //decide whether phase information is relevant { usePhase = 0; //-> phase ignored } else if ((P3_DATA & 0x2) == 0) //decide which contactor is used for shoot { mainc = 0; //serial contactors are used } else counter = 0; break; } }
-
Hallo,
den Vorschlag hat mir Zustandsautomat auch schon gemacht. Das Problem daran ist, dass es kein Fehler ist, wenn eine Kombination übergeben wird, die nicht in den Abfragen abgefangen wird! Das wird später sogar die Regel sein und die if-else-Blöcke kommen ja auch wieder aus dem Programm raus.
Ich DARF den counter also gar nicht 0 setzen, weil er sonst ja erst recht in die falschen Variablen reinschreibt.