mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Immer noch Fehler!


Autor: Dennis (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Dennis (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, hier die andere C-Datei!!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Diese ganze Sequenz
    TCNT1 = startval;            // 36ms
    TCCR1B = 0x03;              // Timer starten 36ms

    while ((PINC = a))            // Auf Ende des Echos warten
    {
      asm volatile ("nop");        // und solange nix machen
    }

    // Echodauer verarbeiten
    if (interrupt == 1)            // Zwischenzeitlich Interrupt?
    {
      control[(i >> 1)] = 3270;      // Mehr als 3m Platz
      interrupt = 0;            // Meldevariable l?en
    }
    else
    {
      control[(i >> 1)] = TCNT1 - startval;
                        // Abstand auswerten...
      TCCR1B = 0x00;            // ...und Timer stoppen
      interrupt = 0;            // vorsichtshalber
    }

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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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?

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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!!!

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ... ich nehm jetzt mal das Brett vom Kopf und dann schauen wir mal 
weiter..

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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 ;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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"

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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 ;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar!!

Ich danke Euch sehr für Eure Hilfe!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.