Hallo alle zusammen, ich hatte in den vergangenen Tagen schon mein Problem mit der SPI eines Atmega32 gepostet. Ich stelle nun den kompletten Code dazu, damit mir (vielleicht) jemand helfen. Kurz zur Konfiguration: Mastercontroller (Steuerung) ================ PA0 bis PA2 --> Triggerausgänge Ultraschallsensoren PC5 bis PC7 --> Echoeingänge Ultraschallsensoren Slavecontroller (Fahrwerk) =============== PB3 --> PWM-Ausgang Maschine 1 PD7 --> PWM-Ausgang Maschine 2 Beide Controller sind über SPI miteinander verbunden. Das Problem: Aus einem mir nicht verständlichen Grund kommen die gesendeten Bytes auf dem Slavecontroller teilweise in einer anderen Reihenfolge an. Ich vermute, dass Bytes "verschluckt" werden, also verloren gehen. Den Grund dafür habe ich nicht gefunden. Und weiter weiss ich leider auch nicht mehr. Ich hoffe, dass mir von Euch jemand helfen kann! Grüße und Danke! Dennis Die andere C-Datei poste ich hier nach!
Das hier Steuerung.c
1 | while (!((PINC = a))) // Auf Echo warten (dauert 200us) |
2 | {
|
3 | asm volatile ("nop"); // und solange nix machen |
4 | }
|
sieht nicht koscher aus. Wozu soll es gut sein an PINC den Wert von a zuzuweisen?
Das hier
1 | // gesendet wurde erst Low-Byte dann High-Byte
|
2 | gap[a] = ((unsigned int) letter[(i+1)]) | (unsigned int) letter[i]; |
stimmt auch nicht du musst letter[i+1] schon um 8 Bits nach links schieben.
Diese ganze Sequenz
1 | TCNT1 = startval; // 36ms |
2 | TCCR1B = 0x03; // Timer starten 36ms |
3 | |
4 | while ((PINC = a)) // Auf Ende des Echos warten |
5 | {
|
6 | asm volatile ("nop"); // und solange nix machen |
7 | }
|
8 | |
9 | // Echodauer verarbeiten
|
10 | if (interrupt == 1) // Zwischenzeitlich Interrupt? |
11 | {
|
12 | control[(i >> 1)] = 3270; // Mehr als 3m Platz |
13 | interrupt = 0; // Meldevariable l?en |
14 | }
|
15 | else
|
16 | {
|
17 | control[(i >> 1)] = TCNT1 - startval; |
18 | // Abstand auswerten...
|
19 | TCCR1B = 0x00; // ...und Timer stoppen |
20 | interrupt = 0; // vorsichtshalber |
21 | }
|
sieht nicht gut aus. Du startest zwar den Timer. Du stoppst ihn aber irgendwann (wann eigentlich) und rechnest zwischendurch mit dem TCNT1 Wert rum, als ob es kein morgen gäbe. So wirst du nie ein vernünftiges Timing kriegen. Darf ich einen Vorschlag machen? Ehe du mit dem SPI rummachst, gib dir doch die gemessenen Werte erst mal irgendwo aus (UART, PORT, LCD oder was du zur Verfügung hast) und mach erst mal deine Hausaufgaben einer vernünftigen, zuverlässigen Messung. Es bringt nichts sich an 3 Fronten gleichzeitig aufzureiben. Ein Subsystem nach dem anderen debuggen, lauffähig machen und deren korrekte Funktion sicherstellen.
> Aus einem mir nicht verständlichen Grund kommen die > gesendeten Bytes auf dem Slavecontroller teilweise in einer > anderen Reihenfolge an. Ich vermute, dass Bytes "verschluckt" > werden, also verloren gehen. Das Wort, welches mich in diesem Absatz erschreckt ist "vermute". Mit Vermutungen kommt man nicht weiter. Fakten zählen! Wenn du den Verdacht hast, dass da irgendetwas in einer falschen Reihenfolge passiert, dann schaff dir eine Möglichkeit, wie du dir Werte ansehen kannst. Alles andere ist stochern im Nebel. Bei der Fehlersuche darf man nicht 'vermuten', man muss wissen! Wissen kann man aber nur Dinge, die man mit eigenen Augen gesehen hat, weil einem das Programm Zwischenwerte in irgendeiner Form anzeigt.
> Das hier > Steuerung.c > while (!((PINC = a))) // Auf Echo warten (dauert 200us) > { > asm volatile ("nop"); // und solange nix machen > } > sieht nicht koscher aus. > Wozu soll es gut sein an PINC den Wert von a zuzuweisen? Es funktioniert aber. Die Ultraschallmessung läuft einwandfrei. Es geht sich nur um die SPI-Übertragung. Wenn ich die Auswertung auf "Start" oder "Stopp" in der Steuerung mache und nur ein Byte sende, dann funktioniert es. Sende ich 6 Bytes, klappt es nicht mehr. > Das hier > // gesendet wurde erst Low-Byte dann High-Byte > gap[a] = ((unsigned int) letter[(i+1)]) | (unsigned int) letter[i]; > stimmt auch nicht > du musst letter[i+1] schon um 8 Bits nach links schieben. Stimmt leider doch. Ich habe das mit AVR-Simulator überprüft. Im SPI-Senderegister kommen die richtigen Werte an. Ich habe das überprüft, in dem ich Werte vor gegeben habe. > Darf ich einen Vorschlag machen? Klar ;) > Ehe du mit dem SPI rummachst, gib dir doch die gemessenen Werte erst mal > irgendwo aus (UART, PORT, LCD oder was du zur Verfügung hast) und mach > erst mal deine Hausaufgaben einer vernünftigen, zuverlässigen Messung. > Es bringt nichts sich an 3 Fronten gleichzeitig aufzureiben. Ein > Subsystem nach dem anderen debuggen, lauffähig machen und deren korrekte > Funktion sicherstellen. Guter Vorschlag. Eigentlich mache ich das ja auch so. Wie gesagt ... die Ultraschallmessung läuft ja. Und sende ich dem Fahrwerk nur die Info "1" oder "0", sprich ein Byte, macht die Kiste alles was ich will. Sobald 6 Bytes gesendet werden, gehen Infos verloren. > Das Wort, welches mich in diesem Absatz erschreckt ist "vermute". Warum? Ich programmiere noch nicht so lange. Hast Du immer gleich alles gewusst?
> Das hier > // gesendet wurde erst Low-Byte dann High-Byte > gap[a] = ((unsigned int) letter[(i+1)]) | (unsigned int) letter[i]; > stimmt auch nicht > du musst letter[i+1] schon um 8 Bits nach links schieben. Entschuldigung!! Hast Recht. Ich habe das Schieben vergessen!!!
Und was ist mit dem ersten? Du machst eine Zuweisung auf PINC und keinen Vergleich! Das ist definitiv nicht gewollt, da du so nicht PINC abfragst sondern er verlässt die Schleife wenn a 0 ist. Wenn das gewollt ist, dann kannst du dir das ansprechen von PINC sparen. Also denk nochmal drüber nach...
Er soll abfragen, ob der Wert, der am Port ansteht dem Wert von a entspricht. Dann muss da stehen a = PINC, oder?! Also genau anders herum.
Dennis schrieb: > Er soll abfragen, ob der Wert, der am Port ansteht dem Wert von a > entspricht. > Dann muss da stehen a = PINC, oder?! Also genau anders herum. Vergleich schreibt sich in C immer noch als == Das Tolle daran ist, dass ihn der Compiler sogar gewarnt hat: "Bist du dir sicher, dass das eine Zuweisung sein soll und kein Vergleich? Wenn du dir 100%, absolut sicher bist, dann schlage ich vor, du machst noch eine Klammer drumherum." Und das hat er dann auch getan while ((PINC = a)) // Auf Ende des Echos warten
Ja ... ich nehm jetzt mal das Brett vom Kopf und dann schauen wir mal weiter..
> Das Tolle daran ist, dass ihn der Compiler sogar gewarnt hat: > "Bist du dir sicher, dass das eine Zuweisung sein soll und kein > Vergleich? Wenn du dir 100%, absolut sicher bist, dann schlage ich vor, > du machst noch eine Klammer drumherum." Das ist nicht passiert. WEnn ich in AVR Studio 4.0 kompiliere, steht da "Build succeeded with 0 Warnings" Über mich lustig machen brauchst Du Dich nicht ;)
Dennis schrieb: >> sieht nicht koscher aus. >> Wozu soll es gut sein an PINC den Wert von a zuzuweisen? > > Es funktioniert aber. Die Ultraschallmessung läuft einwandfrei. Das glaube ich nicht. Eine Zuweisung ist kein Vergleich! >> Das hier > >> // gesendet wurde erst Low-Byte dann High-Byte >> gap[a] = ((unsigned int) letter[(i+1)]) | (unsigned int) letter[i]; > >> stimmt auch nicht >> du musst letter[i+1] schon um 8 Bits nach links schieben. > > Stimmt leider doch. Ich habe das mit AVR-Simulator überprüft. Auch das kann ich mir nicht vorstellen. Wenn du 8 Bit mit anderen 8 Bit veroderst kommt alles mögliche raus. Aber sicher nicht eine vernünftige 16 Bit Zahl. Das Ergebnis von 0x0020 | 0x0040 ist nun mal 0x0060 und nicht 0x2040, so wie es eigentlich sein sollte, wenn du 2 einzelne Bytes (nämlich 0x20 und 0x40) zu einem int zusammensetzt. (Man könnte es auch so sagen: Wenn du beim Senden einen Teil der Zahl um 8 Stellen nach rechts schiebst, dann muss genau dieser empfangene Teil im Empfänger wieder um 8 Stellen nach links geschoben werden, damit er wieder an seiner ursprünglichen Lage zu liegen kommt) >> Das Wort, welches mich in diesem Absatz erschreckt ist "vermute". > > Warum? Ich programmiere noch nicht so lange. Hast Du immer gleich alles > gewusst? Nein. Aber genau deshalb erzähl ich es dir, wie man an die Dinge rangeht. Ich könnte dich auch noch ein paar Tage im Nebel stochern lassen!
>> Das hier > >> // gesendet wurde erst Low-Byte dann High-Byte >> gap[a] = ((unsigned int) letter[(i+1)]) | (unsigned int) letter[i]; > >> stimmt auch nicht >> du musst letter[i+1] schon um 8 Bits nach links schieben. > > Stimmt leider doch. Ich habe das mit AVR-Simulator überprüft. > Auch das kann ich mir nicht vorstellen. > Wenn du 8 Bit mit anderen 8 Bit veroderst kommt alles mögliche raus. > Aber sicher nicht eine vernünftige 16 Bit Zahl. > Das Ergebnis von 0x0020 | 0x0040 ist nun mal 0x0060 und nicht 0x2040, > so wie es eigentlich sein sollte, wenn du 2 einzelne Bytes (nämlich 0x20 > und 0x40) zu einem int zusammensetzt. > (Man könnte es auch so sagen: > Wenn du beim Senden einen Teil der Zahl um 8 Stellen nach rechts > schiebst, dann muss genau dieser empfangene Teil im Empfänger wieder um > 8 Stellen nach links geschoben werden, damit er wieder an seiner > ursprünglichen Lage zu liegen kommt) Du hast ja Recht. Ich habe das nur auf der anderen Seite überprüft. Diesen Teil habe ich nicht gecheckt. Genau diese Zeile bestätigt damit ja auch meine Vermutung, dass Bytes verloren gehen. Nämlich jeweils das Low-Byte, weil es vom High-Byte deswegen überschrieben wird, da ich es versäumt hatte, es um 8 Bits nach links zu schieben. > Nein. Aber genau deshalb erzähl ich es dir, wie man an die Dinge > rangeht. Ich könnte dich auch noch ein paar Tage im Nebel stochern > lassen! ISt schon OK! Ich danke Dir ja auch dafür.
Dennis schrieb: >> Das Tolle daran ist, dass ihn der Compiler sogar gewarnt hat: >> "Bist du dir sicher, dass das eine Zuweisung sein soll und kein >> Vergleich? Wenn du dir 100%, absolut sicher bist, dann schlage ich vor, >> du machst noch eine Klammer drumherum." > > Das ist nicht passiert. WEnn ich in AVR Studio 4.0 kompiliere, steht da > "Build succeeded with 0 Warnings" > > Über mich lustig machen brauchst Du Dich nicht ;) Tu ich nicht. Aber schreib mal testweise while (PINC = a) // Auf Ende des Echos warten also nur mit einer Klammer :-) und schau nach, was der gcc dazu sagt :-) Und da ich nicht davon ausgehe, dass jemand freiwillig hier bei einem irrtümlichen Vergleich ein zusätzliches Klammernpaar schreibt, hattest du das ursprünglich so ..., while (PINC = a) // Auf Ende des Echos warten ... der Compiler hat dich gewarnt und du hast das 2.te Klammerpaar dazugemacht: while ((PINC = a)) // Auf Ende des Echos warten wenn eigentlich while (PINC == a) // Auf Ende des Echos warten richtig gewesen wäre Nimms doch nicht persönlich! Genau dieser Fehler passiert tausende male am Tag. Und genau aus diesem Grund gibt es diese Warnung. Der COmpiler kann aber nicht wissen, welche der beiden Varianten richtig ist und gibt daher den Hinweis, wie man die Warnung los werden kann, wenn man sich absolut 100% sicher ist, dass die Zuweisung gewollt ist. Was du daraus lernen sollst: Compilerwarnungen und vor allen Dingen Vorschläge, die darin enthalten sind, nicht für Gottes letztes Wort zu nehmen, sondern selbst noch einmal nachdenken: Hier stimmt was nicht, was könnte es sein?
> Und da ich nicht davon ausgehe, dass jemand freiwillig hier bei einem > irrtümlichen Vergleich ein einzelnes = schreibt, hattest du das > ursprünglich so, der Compiler hat dich gewarnt und du hast das 2.te > Klammerpaar dazugemacht. Jep :-D
Dennis schrieb: > ... > Warum? Ich programmiere noch nicht so lange. Hast Du immer gleich alles > gewusst? Karl heinz Buchegger ist auch Anfänger, und weiß es trotzdem: Beitrag "Re: Kann man ne this global über ne operatorfunktion"
> Karl heinz Buchegger ist auch Anfänger, und weiß es trotzdem: > Beitrag "Kann man ne this global über ne operatorfunktion" Thema ist doch schon gehalten. Bleiben wir beim Fachlichen, okay ;)
Karl heinz Buchegger schrieb: > wenn eigentlich > while (PINC == a) // Auf Ende des Echos warten > richtig gewesen wäre Wobei selbst das noch fraglich ist, ob das tatsächlich so richtig ist, Oder ob das in Wirklichkeit nicht while( PINC & a ) heißen müsste.
Ist das Ergebnis nicht dasselbe? Einmal fragt man auf Gleichheit ab, das andere Mal maskiert man und setzt damit gleichfalls voraus, dass beide Ergebnisse gleich sind, um die Bedingung zu erfüllen. Wo ist da nun genau der Unterschied?
Bei a&b wird das Ergebnis bitweise gebildet, Ergebnis ist eine Zahl, in der alle Bits gesetzt sind, die sowohl in a als auch in b gesetzt sind. Im if wird das auf ungleich 0 getestet. Das if wird also genau dann ausgeführt, wenn a und b mindestens ein gemeinsames gesetztes Bit haben. Bei a==b kommt entweder 0 heraus oder 1. 1 ergibt sich genau dann, wenn a und b in allen Bits exakt übereinstimmen. 0&0 ergibt 0 0==0 ergibt 1 1&3 ergibt 1 1==3 ergibt 0 7&3 ergibt 3 7==3 ergibt 0
Dennis schrieb:
> Wo ist da nun genau der Unterschied?
Der Unterschied kommt dann zum tragen, wenn in PINC auch noch andere
Bits gesetzt sind, als das an dem du deinen einen Empfänger
angeschlossen hast.
Bei
PINC & 0x80
betrachtest du wirklich nur genau dieses eine Bit (das 7-te Bit) und
sonst nichts. Alle anderen Bits können stehen wie sie wollen, sie
beeinflussen das Ergebnis nicht.
Bei
PINC == 0x80
müssen die anderen Bits alle 0 sein. Ist auch nur eines davon nicht 0,
wird die Abfrage schief gehen, selbst wenn Bit 7 auf 1 steht.
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.