Hi zusammen, ich habe eine Problem und komme nicht weiter. Suche im Netz hat nicht geholfen. Ich hoffe hier finde ich Hilfe?! Ich arbeite mit einem ATMEGA8 und ImageCraftCV v8 (ICCAVR). Mein Problem ist, um den AD Wandler vernünftig auszuwerten muss ich, um Kommarechnung zu vermeiden, kurzzeitig den 16-Bit Bereich verlassen und benötige 32Bit Variablen. Deklarieren kann ich sie auch (uint32_t wird akzeptiert), aber er rechnet dennoch nur mit 16Bit. Liegt's am ATMEGA8? Ich dachte er würde es in 4x8 ablegen und irgendwie berechnen können (Compiler)? Vielen Dank und Gruß, Malte
Malte schrieb: > Deklarieren kann ich sie auch (uint32_t wird akzeptiert), aber er > rechnet dennoch nur mit 16Bit. Das liegt ziemlich sicher nicht am Compiler sondern am Code. Nur diskutiert es sich besser über Code den man kennt. Einen Tipp ins Blaue hätte ich aber trotzdem: Der Typ links vom "=" hat keinerlei Einfluss darauf, wie der Ausdruck rechts davon berechnet wird. uint32_t result = 10000 * 10000; geht bei 16-Bittern also definitiv in die Fritten. PS: Was hat der Imagecraft Compiler mit dem GCC zu tun?
A. K. schrieb: > Einen Tipp ins Blaue hätte ich aber trotzdem: Auf dasselbe Problem hätte ich auch getippt: Der OT hat wieder mal seine Hausaufgaben nicht gemacht und will das jetzt dem Compiler anhängen :-) Etwas näher beleuchtet ist die vermutete Problematik hier:http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen Einfach anstelle von double/float gedanklich uint32_t einsetzen. Ist das gleiche "Problem".
Danke für eure Antworten... Wahrscheinlich ist euer Tipps in Blaue schon ein Volltreffer! Habe ich nicht drüber nachgedacht. Ich teste das mal und sonst veröffentliche mal den Code... Danke! VG, Malte
Hi! Also der Tipp ins Blaue hat nicht ganz in Schwarze getroffen. Der Code ist recht umfangreich, mittlerweile, aber ich habe mir ein Beispiel geschrieben, um diesen Teil zu testen. Ganz simpel: ------------------- int16_t current=0; int32_t current_avr=0; char Buffer[20]; // in diesem {} lokal current_avr=100000; current=current_avr/100; itoa( Buffer, current, 10 ); //Strom dezimal umwandeln in ASCII lcd_string(Buffer); ------------------- So - nun kann ich auf meinen LC Display das sehen: Stelle ich current_avr auf 10000 wird mir 100 auf dem Display angezeigt. Stelle ich ihn auf 100000 (32 Bit Bereich) wird mir -310 angezeigt. Ich habe das Gefühl, der ATMEGA8 begrenzt die Anzahl und kann keine 32Bit oder mache ich etwas falsch? Danke!
Gibt Dein Compiler bei "current_avr=100000;" denn keine Warnung aus? 100000 ist nämlich vom Typ int (also 16) bit lang, passt jedoch garnicht in einen 16-bit int rein -> die restlichen bits werden abgeschnitten und die Zahl wird in diesem Fall ein negativer int, was -31073 ist, soweit ich richtig gerechnet habe. Dacher auch die -310. Deshalb musst Du ein L nach 100000 schreiben, also current_avr=100000L; Dies sagt dem Compiler, dass die Zahl ein 32-bit long ist. MfG Mark
Malte schrieb: > Der Code ist recht umfangreich, mittlerweile, aber ich habe mir ein > Beispiel geschrieben, um diesen Teil zu testen. Das ist der richtige Weg > ------------------- > int16_t current=0; > int32_t current_avr=0; > char Buffer[20]; // in diesem {} lokal > > current_avr=100000; > current=current_avr/100; > > itoa( Buffer, current, 10 ); //Strom dezimal umwandeln in ASCII > lcd_string(Buffer); > ------------------- > > So - nun kann ich auf meinen LC Display das sehen: > > Stelle ich current_avr auf 10000 wird mir 100 auf dem Display angezeigt. > Stelle ich ihn auf 100000 (32 Bit Bereich) wird mir -310 angezeigt. Und das ist wirklich dein Code? 100% so läuft der ab? Kannst du mal ein komplettes Beispiel fertig machen, welches man hier kompilieren kann (die LCD Routinen kannst du dir sparen) > Ich habe das Gefühl, der ATMEGA8 begrenzt die Anzahl und kann keine > 32Bit oder mache ich etwas falsch? Der Mega8 hat damit nichts zu tun. Der führt nur Befehle aus. Befehle die ihm der Compiler erzeugt.
mork schrieb: > Gibt Dein Compiler bei "current_avr=100000;" denn keine Warnung aus? > 100000 ist nämlich vom Typ int (also 16) bit lang, ist es nicht passt jedoch garnicht > in einen 16-bit int rein genau deswegen ist es kein int, sondern ein long
Der ICCAVR8 vertseht kein int16_t oder int32_t oder dergleichen,habs grad getestet. Welchen Compiler verwendest du also bzw. wie ist dein int16_t etc. definiert?
@Karl heinz Buchegger Ok, das current_avr ist wirklich ein long, hab das beim Schreiben irgendwie nicht ganz beachtet. Aber wieso ist 100000 kein int?
mork schrieb: > @Karl heinz Buchegger > > Ok, das current_avr ist wirklich ein long, hab das beim Schreiben > irgendwie nicht ganz beachtet. > > Aber wieso ist 100000 kein int? 2^16 = 65536
mork schrieb: > Aber wieso ist 100000 kein int? Weil es zu groß für einen 16 Bit int ist. Ist ganz einfach: Ist eine Konstante für einen Datentyp zu groß, dann kriegt sie automatisch den nächstgrößeren Datentyp in den sie reinpasst. Sooo dämlich waren Kernighan&Ritchie dann auch wieder nicht. Und für den Compiler ist das eine leichte Übung.
Ja e Daniel V. schrieb: > mork schrieb: >> @Karl heinz Buchegger >> >> Ok, das current_avr ist wirklich ein long, hab das beim Schreiben >> irgendwie nicht ganz beachtet. >> >> Aber wieso ist 100000 kein int? > > 2^16 = 65536 Ja eben. Deshalb passen die 100000 da garnicht rein, und in current_avr steht 100000 - 65536 = 34464. Diese werden als 16-bit signed interpretiert, also - (65536 - 34464) = -31072. (ich glaub irgendwo muss da noch ne +1 1 hin, was aber in diesem Fall egal ist). (31072 +-1) / 100 = -310, eben das, was beim Malte auf dem Display ausgegeben wird. MfG Mark
Karl heinz Buchegger schrieb: > mork schrieb: > >> Aber wieso ist 100000 kein int? > > Weil es zu groß für einen 16 Bit int ist. > Ist ganz einfach: Ist eine Konstante für einen Datentyp zu groß, dann > kriegt sie automatisch den nächstgrößeren Datentyp in den sie reinpasst. > > Sooo dämlich waren Kernighan&Ritchie dann auch wieder nicht. Und für den > Compiler ist das eine leichte Übung. Also vom avr-gcc hab ich das irgendwie anders in Erinnerung. Da muss man doch auch bei größeren Zahlen ständig ein L hintendran hängen, bei Definition von F_CPU z.B.
mork schrieb: > Ja e > > Daniel V. schrieb: >> mork schrieb: >>> @Karl heinz Buchegger >>> >>> Ok, das current_avr ist wirklich ein long, hab das beim Schreiben >>> irgendwie nicht ganz beachtet. >>> >>> Aber wieso ist 100000 kein int? >> >> 2^16 = 65536 > > Ja eben. Deshalb passen die 100000 da garnicht rein, und in current_avr > steht 100000 - 65536 = 34464. Das wäre dann ein Compilerfehler, wenn das passieren würde. Da das aber einer ist, der beim Testen eines COmpilers ganz schnell auffällt, würde ich meine Hand hier nicht auf einen Compilerfehler verwetten. Möglich wärs. Aber sehr unwahrscheinlich.
mork schrieb: > Also vom avr-gcc hab ich das irgendwie anders in Erinnerung. Da muss man > doch auch bei größeren Zahlen ständig ein L hintendran hängen, bei > Definition von F_CPU z.B. Bitte! Kauf dir ein C-Buch und arbeite es durch! Es spielt keine Rolle, woran du dich erinnerst und woran nicht. Entscheidend ist, was in den Normungsdokumenten zu C steht. Und dort steht drinnen, dass auf einer Maschine mit 16-Bit int die Konstante 100000 den Datentyp long hat. OK, in diesem Wortlaut steht es nicht drinnen, aber darauf läuft es hinaus.
> ------------------- > int16_t current=0; > int32_t current_avr=0; > char Buffer[20]; // in diesem {} lokal > > current_avr=100000; > current=current_avr/100; > > itoa( Buffer, current, 10 ); //Strom dezimal umwandeln in ASCII > lcd_string(Buffer); > ------------------- > Also current_avr ist ja 32Bit, da kann man 100000 zuweisen. Die Zeile "current = current_avr / 100" könnte durchaus Probleme machen. Vielleicht so besser?: current_avr = current_avr / 100; current = (int)current_avr;
Karl heinz Buchegger schrieb: > mork schrieb: > >> Also vom avr-gcc hab ich das irgendwie anders in Erinnerung. Da muss man >> doch auch bei größeren Zahlen ständig ein L hintendran hängen, bei >> Definition von F_CPU z.B. > > Bitte! > > Kauf dir ein C-Buch und arbeite es durch! > Es spielt keine Rolle, woran du dich erinnerst und woran nicht. > Entscheidend ist, was in den Normungsdokumenten zu C steht. Und dort > steht drinnen, dass auf einer Maschine mit 16-Bit int die Konstante > 100000 den Datentyp long hat. > OK, in diesem Wortlaut steht es nicht drinnen, aber darauf läuft es > hinaus. Habs gerade ausprobiert, bei uint32_t = 100000; kommt keine Warnung -> wird wohl stimmen. Was ich dann aber nicht vestehe ist, wieso der L-Suffix überhaupt gebraucht, wenn die Zahl schon sowieso ein long ist. Beim Rechnen wird doch mit dem größten Typ aber mindestens mit int gerechnet oder nicht? MfG Mark
mork schrieb: >Was ich dann aber nicht vestehe ist, wieso der > L-Suffix überhaupt gebraucht, wenn die Zahl schon sowieso ein long ist. > Beim Rechnen wird doch mit dem größten Typ aber mindestens mit int > gerechnet oder nicht? Die Suffixe wirste bei DEFINES verwenden, nicht bei Deklarationen von Variablen. Sie helfen dem Compiler beim Berechnen von konstanten Ausdrücken, Rechtzeitig den "int"-Bereich zugunsten von long zu verlassen.
Also ich habe jetzt mal Folgendes gemacht: current_avr=100000L; current_avr=current_avr/100; current=(int)current_avr; Hilft aber auch nicht. Also weder die INT Wandlung noch die L Geschichte. Mein Compiler hat keine Warnung ausgegeben und ich dachte auch, es wäre ok. Schließlich habe ich die current_avr als 32Bit definiert - dann müsste man doch 100.000 zuweisen können, oder? Compiler ist wie gesagt der interne von ICCAVR 8.01. Aber der Compiler muss ja irgendwie dem kleinen 8-Bit Controller die 16-Bit-Werte beibringen. Da es mit 16Bit geht, dachte ich, er würde auch den 32Bit Wert schön zerlegen und in getennten Registern dann behandeln aber irgendwie klappt das nicht. Der Code ist jetzt ein kleines Extrakt und oft kann der Fehler ja auch woanders stecken. Nur in diesem Fall ist es ja recht einfach: die Ausgabefunktion funktioniert auf dem LCD 1A. D.h. dadurch kann ich den 16-Bit Inhalt von current gut visualisieren. Ich habe jetzt mal 32700 eingeben --> Ausgabe 327. Geht. Dann 32800 bei current_avr. Ausgabe über current --> 327. Spricht ja dafür, dass er current_avr als int16_t und nicht als int32_t ansteuert... Verstehe ich einfach noch nicht. Naja, ich muss jetzt eh mal los und vielleicht fällt der Groschen, wenn man an etwas anderes denkt :) Danke euch!
mork schrieb: > wird wohl stimmen. Was ich dann aber nicht vestehe ist, wieso der > L-Suffix überhaupt gebraucht, wenn die Zahl schon sowieso ein long ist. > Beim Rechnen wird doch mit dem größten Typ aber mindestens mit int > gerechnet oder nicht? Weil es ja auch diese Fälle gibt #define QUDARAT_MILLIMETER 1000 * 1000 1000 ist ein int Soweit alles ok. Aber 1000 * 1000 passt nicht mehr in einen int. Die Multiplikation wird überlaufen, weil sie in int durchgeführt wird. #define QUDARAT_MILLIMETER 1000L * 1000L liefert das richtige Ergebnis
Malte schrieb: > Ich habe jetzt mal 32700 eingeben --> Ausgabe 327. Geht. Dann 32800 bei > current_avr. Ausgabe über current --> 327. Spricht ja dafür, dass er > current_avr als int16_t und nicht als int32_t ansteuert... Nein, spricht dafür dass du dich mit den Deklarationen vertan und/oder dir mit wildem Casting selbst ins Bein geschossen hast.
Malte schrieb: > Compiler ist wie gesagt der interne von ICCAVR 8.01. > Aber der Compiler muss ja irgendwie dem kleinen 8-Bit Controller die > 16-Bit-Werte beibringen. Da es mit 16Bit geht, dachte ich, er würde auch > den 32Bit Wert schön zerlegen und in getennten Registern dann behandeln Das tut er auch. Aber er bewegt sich dabei im Rahmen der C-Regeln. Und irgendwo hast du ein Schlupfloch offen gelassen. Und daher nochmal die Bitte: Bitte, ein komplettes, kompilierbares Programm (von mir aus ohne die LCD Funktionen) Bei deinem Problem sind die Details wichtig! Auch die, die du nicht zeigst.
Malte schrieb: > > Compiler ist wie gesagt der interne von ICCAVR 8.01. > Aber der Compiler muss ja irgendwie dem kleinen 8-Bit Controller die > 16-Bit-Werte beibringen. Da es mit 16Bit geht, dachte ich, er würde auch > den 32Bit Wert schön zerlegen und in getennten Registern dann behandeln > aber irgendwie klappt das nicht. > > Der Code ist jetzt ein kleines Extrakt und oft kann der Fehler ja auch > woanders stecken. Nur in diesem Fall ist es ja recht einfach: die > Ausgabefunktion funktioniert auf dem LCD 1A. D.h. dadurch kann ich den > 16-Bit Inhalt von current gut visualisieren. > > Ich habe jetzt mal 32700 eingeben --> Ausgabe 327. Geht. Dann 32800 bei > current_avr. Ausgabe über current --> 327. Spricht ja dafür, dass er > current_avr als int16_t und nicht als int32_t ansteuert... > > Verstehe ich einfach noch nicht. Naja, ich muss jetzt eh mal los und > vielleicht fällt der Groschen, wenn man an etwas anderes denkt :) > > Danke euch! Aaalso, ich hab hier den ICCAVR8.01.07, wenn ich das hier mache:
1 | long current_avr; |
2 | int current; |
3 | |
4 | current_avr = 100000; |
5 | current_avr = current_avr / 100; |
6 | current = (int)current_avr; |
und im Debugger mir die Ergebnisse anschaue, dann erhalte ich für current = 1000. Am Compiler liegt es NICHT! Wie gesagt: "int16_t" oder "int32_t" versteht dieser Compiler NICHT! Wie hast du diese Typdefinitionen definiert? Bitte wie schon offt erwähnt: Kompletter Code posten!
Ja und sogar das:
1 | long current_avr; |
2 | int current; |
3 | |
4 | current_avr = 100000; |
5 | current = current_avr / 100; |
bekommt er richtig hin...
Ach ja, der Vollständigjkeit halber:
1 | char text[20]; |
2 | ...
|
3 | ...
|
4 | itoa(text,current,10); |
Liefert natürlich das richtige Ergebnis, nämlich "1000". Wenn man current_avr als "int" deklariert, dann kommt in der Tat für current -310 raus, wer hätte das gedacht...
Erstmal danke! Sorry, ich konnte nicht früher antworten. Mein Code sind 400 Zeilen... ich müsste erstmal etwas darauf extrahieren, damit es hier im Forum kompiliert werden kann. Ich kann auch alles posten, aber wird wahrscheinlich etwas unübersichtlich. Ich müsste also erstmal einen Extrakt bauen, mach ich dann noch. Der Rest des Codes lief ja auch solange ich in 16Bit Bereichen blieb. Die int32_t definition habe ich wie folgt gemacht: typedef signed char int8_t; typedef signed short int16_t; typedef signed long int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; Ich probiere jetzt erstmal alle Tipps hier aus und dann melde ich mich wieder. Ich finde es super, wie schnell hier einem geholfen wird. Danke nochmal an alle! Wenn ich nicht weiterkomme werde ich auf jeden Fall den Codes extrahieren und kompilierfähig posten! VG, Malte
Ich glaube ich habe es. Es war ein Doppelfehler: Zum einen kann itoa nur 16Bit. Das hatte ich mir schon gedacht, aber beim Spielen dann doch ab und an auch 32Bit übergeben und das ging natürlich nicht. Dann hatte ich noch einen 2ten typedef, da stand short statt long. Die beiden Kombinationen führten dazu, dass nix klappte. Jetzt sieht es sehr gut aus. Weder das "L" ist notwendig noch irgendwas. Es scheint zu gehen :) Danke nochmals! VG, Malte
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.