Guten Morgen!
hab einen ATmega 128 und wenn ich "build" durchführe (AVRstudio) bekomme
ich keine errors, aber immer die selbe Warnung:
dateiname.c:73: warning: large integer implicitly truncated to unsigned
type
Diese Warnung hab ich 13mal, sie meldet jede Zeile in der ich die als
Ausgang definierten Ports A7,C7 & F7 verwende.
Die Warnung kommt aber nicht bei den als Eingang definierten und
verwendeten B7,D7 & E7.
Er sagt ja "unsigned type" aber ich spreche ja immer Ausgänge an und
keine variablen oder verstehe ich die Meldung falsch.
Ausgänge habe ich wie folgt definiert: DDRA=0xff;
Ausgänge spreche ich wie folgt an: PORTF|=(1<<PF7);
Eingänge verarbeite ich wie folgt: PINE&(1<<PINE7);
Kann mir vielleicht jemand erklären, wieso die Meldung kommt, warum nur
bei Ausgängen und nur jeweils bei dem 7.Portpin und was kann ich dagegen
tun???
Danke schon mal
Das kommt vermutlich daher, dass der Wert 128 nicht mehr in den signed
Typ passt und daher der unsigned Typ verwendet wird.
Das der Compiler aber standardmäßig mit int rechnet, sollte diese
warning normalerweise nicht auftauchen. Oder verwendest du einen int mit
nur 8bit?
Also der Kopf meines Programmes ist wie folgt:
#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
// Übung mit Probeplatine !!!
int main (void)
{
Wird bei dem atmega nicht128 nicht grundsätzlich mit 16bit gearbeitet,
wenn man es nicht anders deklariert.
Wenn nicht, wie deklariere ich ihm denn in meinen Fall, dass er mit
16bit arbeitet?
Zeig doch bitte mal das komplette Programm.
Ich hab zwar eine Vermutung und ich denke Benedikt hat die gleiche
Vermutung, aber ich möchte erst sicher gehen, ehe ich mir den Mund
verbrenne
Normalerweise sollte er mit 16bit arbeiten, es gibt allerdings eine
Compileroptionen (heißt glaube ich -mint8), mit der man auf 8bit
umschalten kann. Schau mal ob diese aktiv ist.
Ich denke, die Warnung bezieht sich auf diesen Fall
#define A7 128
...
PORTB = A7;
A7, also 128, ist der 'large Integer'
Und die Zuweisung geht auf einen unsigned char.
Ein
#define A7 128U
sollte das 'Problem' eigentlich beheben.
Das Problem besteht darin, dass in C zunächst aus dem signed 16-Bit ein
signed 8_Bit gemacht wird. Damit ist aber 128 nicht mehr darstellbar.
Erst danach geht es von signed 8-Bit auf unsigned 8-Bit, womit 128
wieder eine korrekte Darstellung besitzt.
>Compileroptionen (heißt glaube ich -mint8), mit der man auf 8bit
Davon hab ich noch nicht gehört, wie funktioniert das den genau das ich
das überprüfen und umstellen kann?
hallo kbuchegg,
was vermutest du denn, einfach mal raus damit! Bin ja für jede Hilfe
dankbar und wenns halt nicht klappt, ist nicht schlimm.Also keine Angst,
dass du dir den Mund verbrennst.
>#define A7 128U
also das dann zu beginn mit allen 7. Portpins die ich als Ausgang
verwende, also in meinem Fall dann...
#define A7 128U
#define C7 128U
#define F7 128U
int main (void)
{
usw.
Oder muss ich dann noch irgendwo was beachten oder einbinden?
Stefan schrieb:
>>#define A7 128U>> also das dann zu beginn mit allen 7. Portpins die ich als Ausgang> verwende, also in meinem Fall dann...>>> #define A7 128U> #define C7 128U> #define F7 128U>> int main (void)> {> usw.>>> Oder muss ich dann noch irgendwo was beachten oder einbinden?
Das U hinter einer Zahl markiert die Zahl als 'unsigned'. So wie ein 'L'
die Zahl als long markiert oder ein 'F' eine Gleikommazahl als float
markiert. Diese Postfixe sind Bestandteil der Zahl, so wie ein
Vorzeichen Bestandteil einer Zahl ist.
-> C Buch lesen
(Hast du es schon probiert? Löst das dein 'Problem')
Karl heinz Buchegger schrieb:
> Ich denke, die Warnung bezieht sich auf diesen Fall>> #define A7 128
Denke ich nicht, denn dann würde der Fehler auch bei 1<<64 (also A6
usw.) auftreten.
Desweiteren sind die ganzen Portbits beim avrgcc als Bitnummer, also
#define A7 7 definiert und nicht als #define A7 128.
Daher bleibe ich bei der Vermutung mit mint oder etwas ähnlichem.
@Stefan
Poste am besten mal das komplette Programm inklusive aller weiteren zum
Projekt gehörenden Dateien.
Benedikt K. schrieb:
> Karl heinz Buchegger schrieb:>> Ich denke, die Warnung bezieht sich auf diesen Fall>>>> #define A7 128>> Denke ich nicht, denn dann würde der Fehler auch bei 1<<64 (also A6> usw.) auftreten.
Mag vielleicht ein Tippfehler im Ursprungsposting sein, aber die
vordefinierte Pinnummer heissen PA7, nicht A7.
Von daher denke ich, dass er da irgendeinen selbstgebastelten
Mechanismus benutzt, der zum Problem führt.
> Daher bleibe ich bei der Vermutung mit mint oder etwas ähnlichem.
Kann auch sein.
> Poste am besten mal das komplette Programm inklusive aller weiteren zum> Projekt gehörenden Dateien.
Das ist sicherlich die beste Lösung.
Hier mal der code!
Ich denke jetzt mal, dass das kein Programmierfehler ist sondern ein
Definitionsfehler.
Weil er gibt mir ja beim compilieren kein 'error' sondern nur eine
'warnung'!
Ich hoffe, durch das Programm kann man auf den Fehler schließen.
Hall zusammen,
ich schalte mich hier mal ein weil Coder zur 7Segment Ansteuerung bei
mir dieselbe Warnung verursacht. Der Code ist aus dem DCF77-Funkwecker
Beispiel abgwandelt....
Stefan schrieb:
> Weil er gibt mir ja beim compilieren kein 'error' sondern nur eine> 'warnung'!
Nein. Es kommen errors, da anscheinend ein paar Klammern zu wenig sind.
main.c:27: warning: large integer implicitly truncated to unsigned type
main.c:74: warning: large integer implicitly truncated to unsigned type
main.c:112: warning: large integer implicitly truncated to unsigned type
main.c:137: warning: large integer implicitly truncated to unsigned type
main.c:167: warning: large integer implicitly truncated to unsigned type
main.c:172: warning: large integer implicitly truncated to unsigned type
main.c:192: warning: large integer implicitly truncated to unsigned type
main.c:247: warning: large integer implicitly truncated to unsigned type
main.c:271: warning: large integer implicitly truncated to unsigned type
main.c:302: warning: large integer implicitly truncated to unsigned type
main.c:307: warning: large integer implicitly truncated to unsigned type
main.c:326: warning: large integer implicitly truncated to unsigned type
main.c:349: error: expected declaration or statement at end of input
main.c:349: error: expected declaration or statement at end of input
make.exe: *** [main.o] Error 1
Das Problem liegt anscheinend in diesen Zeilen in denen eine Zahl >=128
negiert wird:
PORTC=~0xc0; // Ausgänge auf 0 setzen
>Der Code erzeugt zwar Warnungen funktioniert aber anscheinend>einwandfrei.
Also kann es sein, dass das Programm trotz Warnung fehlerfrei läuft? Hab
das ganze nämlich mit vorsicht genossen, damit ich mir nachher nicht
irgendwas schieße!
>Nein. Es kommen errors, da anscheinend ein paar Klammern zu wenig sind.>Wenn man das korrigiert, dann verschwinden auch die Warnings.
Da muss mir beim heraus und herum kopieren ein Fehler passiert sein,
weil bei mir gab es keine "errors" nur die Warnungen bezüglich der
7.Ausgangsports.
Benedikt K. schrieb:
> Das Problem liegt anscheinend in diesen Zeilen in denen eine Zahl >=128> negiert wird:> PORTC=~0xc0; // Ausgänge auf 0 setzen
Ja, das hab ich auch gesehen.
Man muss das Ergebnis des ~ auf unsigned char casten, dann veschwinden
die Warnungen. Die rechte Seite des ~ zu casten ist zuwenig
PORTC = (uint8_t)~0xc0;
Muss jetzt erst mal darüber nachdenken, wie das in den C-Standard
hineinpasst und ob diese Warnung vom gcc zu Recht besteht.
> Ich denke, die Warnung bezieht sich auf diesen Fall>> #define A7 128>> ...>> PORTB = A7;>> A7, also 128, ist der 'large Integer'> Und die Zuweisung geht auf einen unsigned char.
Nein, definitv nein.
A7 ist ein Makro, wird also vom Präprozessor behandelt. Danach steht da
nur noch:
1
PORTB=128;
Und hier steht die 128 als einsames Literal. Da gibt es keine Probleme
mit Signed zu Unsigned.
Die Warnung kommt woanders her. Er soll halt mal den kompletten
Source-Code posten.
Kann ich das Problemm dann beheben, wenn ich diese Zeile umgehe!?
Also anstatt: PORTC=~0xc0
Lieber so: PORTC=~(1<<PC6);
PORTC=~(1<<PC7);
Aber die ZEile bezieht sich ja nur auf den PORTC, aber er warnt ja auch
den PA7 und PF7 an.
Stefan schrieb:
> Kann ich das Problemm dann beheben, wenn ich diese Zeile umgehe!?>> Also anstatt: PORTC=~0xc0>> Lieber so: PORTC=~(1<<PC6);> PORTC=~(1<<PC7);
Nein. Das hilft dir nichts.
PORTC = (unsigned char)~0xC0;
C-Experte schrieb:
> Und hier steht die 128 als einsames Literal. Da gibt es keine Probleme> mit Signed zu Unsigned.
Doch, gibt es. 128 ist ein signed int. ZUgewiesen wird auf einen
unsigned char
Die C Regeln schreiben vor, dass zunächst die Datentyp-Breite angepasst
wird. Also muss aus dem signed int 128 ein signed char 128 gemacht
werden. Und den gibt es nun mal nicht.
Das einzige was mich tatsächlich verblüfft ist, dass der ~operator auch
aus einem unsigned Argument anscheinend ein signed Ergebnis errechnet.
Eigentlich sollte
PORTC = ~( (unsigned char)0xC0);
absolut keine Warnung erzeugen. Im Moment denke ich, dass hier
tatsächlich im gcc was faul ist.
Das bedeutet dann jetzt, dass ich den Pin7 halt nicht als Ausgang
sondern nur als Eingang. Also dann hin und her bauen, damit ich Ausgänge
nur über die jeweiligen Ports von Pin0-6 vergebe???
Stefan schrieb:
> Das bedeutet dann jetzt, dass ich den Pin7 halt nicht als Ausgang> sondern nur als Eingang. Also dann hin und her bauen, damit ich Ausgänge> nur über die jeweiligen Ports von Pin0-6 vergebe???
Nein, das bedeutet es nicht.
Setzt den cast rein, und gut ists.
Der Compiler warnt dich vor einem Fall, der für dich nicht relevant ist.
Wenn du zb schreibst
PORTB = 0x100;
kriegst du dieselbe Warnung. Und hier ist sie auch gut. Dem 8-Bit Objekt
PORTB kann man nun mal nicht 0x100 zuweisen, ohne dass etwas auf der
Strecke bleibt.
Du hast
PORTB = ~0xC0;
Das Bitmuster von 0xC0 ist
0b11000000
davon das Komplement ist (nach den C-Regeln, nach denen alles als int
bzw. unsigned int gerechnet wird)
0b1111111100111111
und wenn man das auf 8 Bit zuweist, fallen ein paar Bits unter den
Tisch, was bei dir nicht weiter stört.
Und um dem Compiler dieses anzuzeigen, dass dieses
Bit-unter-den-Tisch-fallen ok ist, castest du das Ergebnis händisch nach
unsigned char.
In diesem Fall ist der cast nichts anderes als die C-Version von "halts
Maul, ich weiß schon was ich tu".
Das Verblüffende dabei ist, dass dieser Cast m.W. bisher nicht notwendig
war.
Was weiter verblüffend ist:
PORTC = ~0x01;
compiliert ohne Warnung, obwohl hier prinzipiell eigentlich das gleiche
Problem besteht. Es scheint tatsächlich so, dass diese Warnung nur
auftaucht, wenn Bit 7 im Ausgangsmaterial gesetzt ist.
@c-expert: erstens setzt er seine ports ganz anders als du da gerade
beschreibst. 2. sollte da hinter dem 128 ein u für unsigned stehen wie
weiter oben beschrieben.
1
PINE&(1<<PINE7);
Die meldung "warning: large integer implicitly truncated to unsigned
type" erzählt uns etwas von large integer und transcatted to unsigned
type.
bedeutet also, das irgend was signed nach ansigned gewandelt wird; und
zwar vom kompiler, der leider nicht wais ob das was er da gerade macht
auch würklich richtig ist oder nicht. es könnte hierbei in ungewollter
datenverlust oder Informationsverlust aufteten / eine Wertveränderung.
ist sicher etwas dumm wenn aus -1 plützlich 255 wird.
ich vermute mal. das PINE und alle anderen register als "unsigned"
definiert ist. (die Fehlermeldung bestätigt das ja) die 1 in der
anweisung wird als large signed betrachtet. das ist default bei den
compilern (zumindest kenn ich das so) dadurch wird 1<<PINE7 zu 1<<7 =
128 large signed. Das ganze weist du dann einem unsigned zu bzw
verknüfst das ganze damit. Dadurch wird der kompiler jetzt gezwungen
signed mit unsigned zu verarbeiten ohne zu wissen ob das jetzt so
richtig ist oder nicht.
versuch mal das dann solte das verschwinden, bzw er sagt dann das der
bereich rechts grössser ist als der like, dann währe ggf noch ein cast
auf unsigned char nötig.
1
PINE&(1u<<PINE7);
2
PINE&((unsignedchar)(1u<<PINE7));
solche sachen passieren auch wenn man von unsigned variablen etwas
abzieht. das ergebnis ist dann normalerweise signed. der kompiler weis
nicht ob da nicht doch ein sprung ins negative möglich ist.
Vermutlich so sein:
Fall 1:
Der Compiler betrachtet die Zahl 1 als int, negiert diese, aus der 1
wird also 65534 bzw. als int zu einer -2.
Er verkleinert das ganze zu einem char, also wird das -2, draus (also
eine 254). Das passt also in ein char.
Fall 128:
Der Compiler betrachtet die Zahl 128 als int, negiert diese, aus der
128 wird also 65407 bzw. als int zu einer -129.
Er verkleinert das ganze zu einem char, was nicht passt, da char nur bis
-128 geht.
avr schrieb:
> @Buchegger>> Das Problem scheint mit der direkten Zuweisung zusammenzuhängen:>
1
>PORTB=~0xC0;
2
>
>> Nicht bei Verknüpfungen:>
1
>PORTB=0xff;
2
>PORTB&=~0xC0;
3
>
>> Kann das sein?
Kann sein.
Wobei auch hier wieder Verblüffendes passiert
PORTB = PORTB & ~0x80;
ist dem Compiler keine Silbe wert. Konzeptionell, also jetzt nur auf
Datentypen und Wertebereiche bezogen, passiert aber nichts anderes als
bei
PORTB = ~0x80;
In beiden Fällen wird ja ~0x80, bezogen auf Datentypen und
Wertanpassungen, völlig gleich behandelt. Oder überseh ich da was?
(Ich denke wirklich mittlerweile, dass das auf ein Problem im gcc
hindeutet. Er wird schon den korrekten Code dafür erzeugen. Nur die
Umstände, die zur Generierung der Warnung führen, sind ein bischen
undurchsichtig)
Karl heinz Buchegger schrieb:
> PORTB = PORTB & ~0x80;>> ist dem Compiler keine Silbe wert. Konzeptionell, also jetzt nur auf> Datentypen und Wertebereiche bezogen, passiert aber nichts anderes als> bei>> PORTB = ~0x80;
Doch, er führt die & Operation auch als int aus, so dass es vorher zu
keiner Umwandlung auf char und daher zu keinem Überlauf kommt. Und da
das Ergebnis davon zur Compilezeit unbekannt ist, meckert er nicht dass
es einen Überlauf geben könnte.
Die Warning die bei der Umwandlung von einem größeren in einen kleineren
Datentyp erscheinen müsste, wird vermutlich standardmäßig nur
unterdrückt, da die etwas nervig sein würde.
Karl heinz Buchegger schrieb:
> (Ich denke wirklich mittlerweile, dass das auf ein Problem im gcc> hindeutet. Er wird schon den korrekten Code dafür erzeugen. Nur die> Umstände, die zur Generierung der Warnung führen, sind ein bischen> undurchsichtig)
Nachfragen in gcc-help
http://gcc.gnu.org/lists.html
Johann
das mit dem gleichsetzen der typen ist so eine sache. entweder auf den
grössten typ der zeile verwendeten wird, oder operationsweise.
Bei der zuweisung hst du eine 2 Seitigen operator das und einen 1
Seitigen bit Operator die negation und eine zuweisung.
bei der bit negation ist es egal was für einen typ du da reinstopfst. es
geht dir nicht um den variablen typ sondern um die bits. ggf ist dabei
auch die typ überprüfung deaktiviert. bzw es wird der typ verwendet, der
von links gefordert wird.
bei der verundung braucht er für die 2. seite auch einen typ, der sollte
gleich sein mit dem linken. da unbekannte typen per default signed sind
kommt hier ein cast von unsigned char auf unsigned für die linke seite
rein, das ergebniss sollte dann damit signed sein.
bei der zuweisung wird das signed dann auf ein unsigned char zugewiesen.
-> möglicher datenverlust warning
gruss
Benedikt K. schrieb:
> Karl heinz Buchegger schrieb:>> PORTB = PORTB & ~0x80;>>>> ist dem Compiler keine Silbe wert. Konzeptionell, also jetzt nur auf>> Datentypen und Wertebereiche bezogen, passiert aber nichts anderes als>> bei>>>> PORTB = ~0x80;>> Doch, er führt die & Operation auch als int aus, so dass es vorher zu> keiner Umwandlung auf char und daher zu keinem Überlauf kommt. Und da> das Ergebnis davon zur Compilezeit unbekannt ist, meckert er nicht dass> es einen Überlauf geben könnte.
Da ist was dran.
Bei
PORTB & ~0x80
müsste der Ablauf so sein
PORTB auf unsigned int holen
~0x80 als int berechnen
das Ergebnis von ~0x80 unsigned machen
beides und-verknüpfen
Ergebnis auf unsigned char runterholen
zuweisen
> Die Warning die bei der Umwandlung von einem größeren in einen kleineren> Datentyp erscheinen müsste, wird vermutlich standardmäßig nur> unterdrückt, da die etwas nervig sein würde.
Da ist was dran.
Hallo zusammen!
Ich bin der Auslöser für diese Diskussion. Vielleicht schaut ja der eine
oder andere noch einmal herein. Ich hab einfach mal ausprobiert und bin
ein bisschen weiter gekommen.
1. Hab sämtliche verschiedenen Variaten des Port ansprechens ausprobiert
(mit PA7, 0x80, 0b10000000) aber der Fehler/Warnung war immer noch da.
Jedoch kommt die Warnung nur wenn ich den Port zurücksetzen will. Also
wenn die Zeile PORTA=~(1<<PA7); ist dann kommt der Fehler/Warnung. Ist
die Zeile aber zum setzen da PORTA|=(1<<PA7), dann kommt der
Fehler/Warnung nicht.
Vieleicht hat dazu jetzt jemand eine neue Idee woran es liegen könnte.
2. Habe ich mich mit den Fuses noch einmal auseinander gesetzt und mal
die Adressen angeschaut: Extended, High, Low.
Jedem einzelen war eine Adresse zugeordnet z.B. 0x40 oder 0xF2 usw.
Daraufhin habe ich auf "read" geklickt und dann kamen auf einmal andere
Adressen. Da dachte ich dann, ok das sind die zu meinem Controller. Aber
irgendwie ändern die sich jedesmal und sobald dann keine "F" in der
Adressierung stehen und ich neu compiliere, sind Urplötzlich alle
Warnungen weg. Das verwundert mich jetzt, weil wenn ich die DAtei neu
aufrufe sind sie wieder da.
Beim auslesen der "Fuses" ändern sich nicht nur die Adressen auch die
häckchen bei einzelnen Punkten immer wieder aufs neu (z.B: M103C,
JTAGen, SPIEN, usw.)
DAs verstehe ich jetzt nun mal garnicht, kann dazu jemand was sagen!?!?!
Wenn du mehrmals hintereinander das gleiche Programm kompilierst, sieht
der Compiler, dass sich nicht geändert hat, kompiliert also nicht
nochmal und schmeißt daher auch keine warnings.
Wenn die Fusebits sich nicht zuverlässig lesen lassen, würde ich die
Schuld auf den ISP schieben. Kabel zu lang?
> Jedoch kommt die Warnung nur wenn ich den Port zurücksetzen will.> Also wenn die Zeile PORTA=~(1<<PA7);> ist dann kommt der Fehler/Warnung.
Hier löscht du aber nicht nur den Pin7 sondern sezt gleichzeitig ALLE
anderen Pins!
> Ist die Zeile aber zum setzen da PORTA|=(1<<PA7), dann kommt der
Es wurde oben schon gesagt: Da der Wert von PORTA (das ganze ist ja nur
ne kurzschreibweise für PORTA = PORTA | (1<<PA7)) zur COmpilezeit nicht
bekannt ist kann und wird nicht gewarnt.