www.mikrocontroller.net

Forum: Compiler & IDEs je nach Variablenwert Endlosschleife bei ATMega32


Autor: Gallig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich programmiere gerade eine Software für einen ATMega 32. Beim 
ersten Test lief alles Problemlos, jetzt habe ich jedoch eine Variable 
geändert und plötzlich stecke ich anscheinend in einer Endlosschleife.

Durch Debugausgaben auf ein Display konnte ich das Problem auf folgende 
Stelle eingrenzen.
volatile uint16_t puls;    // Pulsbreite des Hauptstroms
volatile uint64_t mittelwert;  // Variable für den Mittelwert
volatile uint8_t messwerte[960];  // Feld für Messwerte von A/D-Wandlung
uint16_t c;      // Zählvariable für FOR-Schleifen

puls=((zih*1000)/290);
for(c=0; c<puls; c++){  // Summe über "Pulsbreite" für ersten Messwert
    mittelwert+=messwerte[c];  // berechnen
}

In der Standardeinstellung hat zih einen Wert von 30 (puls=103)und alles 
läuft ohne Probleme, wenn ich diesen nun auf 40 oder mehr erhöhe bleibt 
das Programm in der FOR-Schleife hängen weil die Variable puls einen 
irrsinnig hohen Wert bekommt, anstatt 137.

Ich habe bisher schon mit verschiedenen anderen Datentypen rumprobiert 
aber das Problem bleibt nach wie vor. Vielleich stehe ich nur auf dem 
Schlauch und bin nach mehreren Stunden der Fehlersuche nur blind für 
meine eigenen Fehler geworden.

Falls also jemand einen Fehler im Code entdeckt oder eine Idee hat wie 
ich das Problem beheben könnte... ich bin für jede Hilfe dankbar.

Ach ja ich programmiere mit AVR-Studio und winavr 20070525,
Optimierung: -Os

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gallig wrote:

> puls=((zih*1000)/290);

> In der Standardeinstellung hat zih einen Wert von 30 (puls=103)und alles
> läuft ohne Probleme, wenn ich diesen nun auf 40 oder mehr erhöhe bleibt
> das Programm in der FOR-Schleife hängen weil die Variable puls einen
> irrsinnig hohen Wert bekommt, anstatt 137.

40 * 1000 = 40000

Beide Seiten haben den Typ `int', der kann nur maximal 32767 darstellen.
Das Ergebnis ist eine negative Zahl: -25536.  Diese wird jetzt durch
290 dividiert, das ergibt -88.  Anschließend erfolgt eine implizite
Typumwandlung auf uint16_t, da das der Zieltyp der Variablen puls ist.
Die Umwandlung von signed nach unsigned int bei gleicher Bitanzahl
ist dabei ein einfaches kopieren des Bitmusters, d. h. das Bitmuster
von -88 wird jetzt nur anders bewertet und heißt dann 65448.

Du musst dich also darum kümmern, dass der innere Multiplikationsterm
nicht überläuft.  Falls zih keine Werte größer 65 annehmen kann,
genügt es dafür bereits, den ganzen Ausdruck komplett in der uint16_t-
Domain zu berechnen:

puls = ((zih * 1000U) / 290U);

Autor: OliverSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler rechnet alles als int, wenn nicht explizit anders 
vorgegeben.

Jetzt schau dir den Wertebereich von int an, dann kommst du auch darauf, 
was da passiert.

Wenn du aus 1000 1000UL machst, sollte es auch mit 40 funktionieren.

Oliver

Autor: Gallig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure schnellen Antworten, jetzt habe sogar ich es 
kapiert ;)
Also werden konstanten generell als INT betrachtet, zufern sie in diesen 
Datentyp "rein passen"?
Richtet sich die Berechnung mit Variablen dann auch immer automatisch 
nach dem größten Datentyp im Term?

Autor: Gallig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch eine kurze Frage, der maximale Wert für zih wäre 300, d.H. ich 
bräuchte bei der Berechnung ein uint32_t wenn ich das soweit richtig 
verstehe. Wie wäre das das Postfix für diesen Datentyp? 1000ULL?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein "L" reicht. "ULL" ist "unsigned long long", das wäre uint64_t.

Autor: Gallig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke :)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gallig wrote:

> Also werden konstanten generell als INT betrachtet, zufern sie in diesen
> Datentyp "rein passen"?

Ja, danach `unsigned int', danach `long', usw.

> Richtet sich die Berechnung mit Variablen dann auch immer automatisch
> nach dem größten Datentyp im Term?

Ja, so kann man das ausdrücken.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ja, danach `unsigned int', danach `long', usw.

Nur wenn die Konstante oktal oder hexadezimal angegeben ist. Bei 
dezimalen ist es 'int', dann 'long', dann 'long long'.

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
puls=((zih*1000U)/290U);
Lässt sich natürlich auch als
puls=((zih*100U)/29U);
Umformen, und schon kann zih zehnmal größer werden, ohne dass die innere 
Klammer den uint16-Wertebereich überschreitet...

Autor: Gallig (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Hilfe. Das mit dem Kürzen ist auch ein guter Tip aber ich 
lasse es lieber so, denke dann ist der Code leichter zu verstehen da die 
Zeitvariable dort von ms in µs umgerechnet wird.

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.