je nach Variablenwert Endlosschleife bei ATMega32

Gast #761762
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.
1
volatile uint16_t puls;    // Pulsbreite des Hauptstroms
2
volatile uint64_t mittelwert;  // Variable für den Mittelwert
3
volatile uint8_t messwerte[960];  // Feld für Messwerte von A/D-Wandlung
4
uint16_t c;      // Zählvariable für FOR-Schleifen
5

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

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
Moderator Persönliche Seite #761777
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);
Gast #761778
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
Gast #761792
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?
Gast #761805
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?
Moderator Persönliche Seite #761819
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.
Gast #761992
> 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'.
Gast #764326
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

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.