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!
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...
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
> 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
> 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.