Hallo,
ich habe soeben ein merkwürdiges Problem. Anbei ein kurzer Ausschnitt:
1
2
uint8_ttempLB=0xc6;// als test
3
4
uint8_ttempHB=d1w_read();
5
//uint8_t tempHB = 0x01;
6
printf("hb: %x\n",tempHB);
7
8
uint16_ttemp=((uint16_t)tempHB<<8)|tempLB;
9
10
printf("temp: %d\n",temp);
d1w_read() gibt den Typ uint8_t zurück. Mit dem oberen Durchlauf erhalte
ich als Rückgabe den Wert 0x01 (printf "hb: 1"). Die Berechnung von temp
ergibt das falsche Ergebnis von Dezimal 2246. In der binärschreibweise
erkennt man den Fehler:
0000 1000 1100 0110
->|
Das 0x01 kommt nicht wie durch tempHB<<8 an die 8te Stelle.
Wenn ich aber nun anstelle
1
uint8_ttempHB=d1w_read();
folgendes ersetze
1
uint8_ttempHB=0x01;
, erhalte ich das richtige Ergebnis von Dezimal 454 und in der
binärschreibweise:
000 0001 1100 0110
->|
tempHB hat wie im oberen Durchlauf auch den Wert von 0x01 (printf: "hb:
1").
Was ist denn da los? Ich kann mir das absolut nicht erklären. Beidesmal
ist tempHB = 0x01, nur einmal wird der Wert durch die Funktion
zugewiesen, und einmal direkt.
Hier noch die Funktion d1w_read():
1
uint8_td1w_read(){
2
3
uint8_tdata=0x00;
4
5
for(uint8_ti=0;i<8;i++){
6
7
// set DDR to output
8
D1W_DDR|=(1<<D1W_DQ);
9
10
// put signal low
11
D1W_PORT&=~(1<<D1W_DQ);
12
13
// hold down for at least 1us
14
_delay_us(1);
15
16
// release by DDR to input
17
D1W_DDR&=~(1<<D1W_DQ);
18
19
// wait
20
_delay_us(10);
21
22
// read 1 (high)
23
if(D1W_PIN&(1<<D1W_DQ)){
24
data|=(1<<i);
25
26
// read 0 (low)
27
}else{
28
29
data&=~(1<<i);
30
31
// wait until high
32
//while (D1W_PIN & (1 << D1W_DQ));
33
}
34
35
// total slot at least 60us
36
_delay_us(55);
37
}
38
39
returndata;
40
}
Ich bin absolut ratlos. Wird durch den Compiler irgendwas wegoptimiert?
Freue mich um jede Hilfe..
Gruß,
Kevin
Mit deinen Infor kann man das Problem nicht nachvollziehen, denn es ist
kein gültiger C-Code.
Um das Problem zu untersuchen, schaue dir den erzeugten Assembler-Code
oder ein Disassembly des erzeuigten o, elf oder hex an.
Ist dieser Code korrekt, dann liegt dein Problem woanners, zB
Stack-Überlauf, Controller ist Fehlpressung, ...
Ist der Code nicht korrekt, dann handelt es sich um einen Tool-Fehler
(Compiler, Linker, Assembler, ...)
Um das Problem nachzuvollziehen braucht man mindestens ein gültiges
(compilierbares) Stückchen C-Code, die Compiler-Version und die
Kommandozeilenoptionen.
Fehlpressung kann ich ausschließen, an einem zweiten AVR tritt der exakt
gleiche Fehler auf. Leider werde ich aus dem reinen Assembler-Code nicht
schlau (*.lss), da ich nicht Assembler spreche. Auch ein diff der beiden
lss-Dateien bringt mich nicht weiter.
Ich kann den Fehler aber noch einfacher reproduzieren:
Falsches Ergebnis (ds18b20_1.zip):
1
uint8_ttempLB=d1w_read();
2
uint8_ttempHB=d1w_read();
3
uint16_ttemp=((uint16_t)tempHB<<8)|tempLB;
4
//printf("%x\n", temp); // <--
5
printf("temp: %d\n",temp);
Ergebnis wie erwartet (ds18b20_2.zip):
1
uint8_ttempLB=d1w_read();
2
uint8_ttempHB=d1w_read();
3
uint16_ttemp=((uint16_t)tempHB<<8)|tempLB;
4
printf("%x\n",temp);// <--
5
printf("temp: %d\n",temp);
Es scheint, als würde die reine Ausgabe von printf() das Ergebnis
verändern. Aus z.b. einem 1d2 (richtig) wird ein 8d2, sobald ich das
printf weglasse.
Das C-File hängt auch im Anhang.
Anbei noch das Compiler-Log:
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
5
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\AVR Studio 5.1\Vs\Compiler.targets" from project "Y:\work\avrstudio\Projects\DS18B20\DS18B20\DS18B20.cproj" (target "Build" depends on it):
6
Task "RunCompilerTask"
7
C:\Program Files (x86)\Atmel\AVR Studio 5.1\make\make.exe all
"C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-objdump.exe" -h -S "DS18B20.elf" > "DS18B20.lss"
24
"C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-size.exe" -C --mcu=atmega328p "DS18B20.elf"
25
AVR Memory Usage
26
----------------
27
Device: atmega328p
28
Program: 2256 bytes (6.9% Full)
29
(.text + .data + .bootloader)
30
Data: 38 bytes (1.9% Full)
31
(.data + .bss + .noinit)
32
Done executing task "RunCompilerTask".
33
Done building target "CoreBuild" in project "DS18B20.cproj".
34
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
35
Target "Build" in file "C:\Program Files (x86)\Atmel\AVR Studio 5.1\Vs\Avr.common.targets" from project "Y:\work\avrstudio\Projects\DS18B20\DS18B20\DS18B20.cproj" (entry point):
36
Done building target "Build" in project "DS18B20.cproj".
> avr-gcc DS18B20.c -S -Os -std=gnu99 -mmcu=atmega328p
gibt:
> DS18B20.c:13:17: fatal error: ser.h: No such file or directory
Ausserdem ist avr-gcc 3.3 asbach uralt. Hol dir mal was neues.
Dein Fehler sieht nach PR46779 aus, gefixt in 4.6.2 oder neuer und auch
in 4.5.4.
Johann L. schrieb:> Ausserdem ist avr-gcc 3.3 asbach uralt. Hol dir mal was neues.
Ich hatte mich auch zunächst über diese ominöse "Version" 3.3.1.27
gewundert, da sie ja mit AVRStudio5.1 so gar nicht zusammenpasst.
Aber bei genauerem Hingucken ist das nicht die gcc-Version, sondern die
Atmel-Versionsnummer ihrer eigenen Toolchain.
Da ich auch das AVRStudio5.1 drauf habe, habe ich mal nachgeschaut:
1
C:\>"C:\Program Files\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc" -v
2
Using built-in specs.
3
COLLECT_GCC=C:\Program Files\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc
4
COLLECT_LTO_WRAPPER=c:/program files/atmel/avr studio 5.1/extensions/atmel/avrgcc/3.3.1.27/avrtoolchain/bin/../libexec/gcc/avr/4.5.1/lt
Frank M. schrieb:> Ist also gcc 4.5.1.
Um PR46779 auszuschliessen, musst du in deinen erzeugten Code schauen
oder ein Update auf 4.5.4, 4.6.2, 4.6.4 oder 4.7.1 machen.
Von 4.6.3 oder 4.7.0 rate ich aus anderen Gründen ab.
Johann L. schrieb:> Frank M. schrieb:>>> Ist also gcc 4.5.1.>> Um PR46779 auszuschliessen, musst du in deinen erzeugten Code schauen> oder ein Update auf 4.5.4, 4.6.2, 4.6.4 oder 4.7.1 machen.
Du verwechselst mich gerade mit dem TO, ich wollte eigentlich nur diese
Info beisteuern ;-)
> Von 4.6.3 oder 4.7.0 rate ich aus anderen Gründen ab.
Hm, ich habe hier auch u.a. die 4.7.0. auf meinem Rechner - auch wenn
ich meist die 4.3.3 (WinAVR20100110) verwende. Könntest Du erläutern,
was an der 4.7.0 zu bemängeln ist? Ist denn die 4.7.1 okay?
Gruß,
Frank
Frank M. schrieb:> Johann L. schrieb:>> Von 4.6.3 oder 4.7.0 rate ich aus anderen Gründen ab.>> Hm, ich habe hier auch u.a. die 4.7.0. auf meinem Rechner - auch wenn> ich meist die 4.3.3 (WinAVR20100110) verwende. Könntest Du erläutern,> was an der 4.7.0 zu bemängeln ist? Ist denn die 4.7.1 okay?
avr-gcc 4.7 hat ein paar neue Features:
- ATXmega Support
- Named Address Spaces wie __flash etc.
- AVR-spezifische Built-Ins wie __buitin_avr_sei()
- 24-Bit Integers
Bei diesen neuen Features gabs ein paar Bugs, die zu falschem Code
führen:
- PR52506, PR52461: ISRs für Xmegas > 64KiB RAM, d.h. mit EBI
- PR53033: wenn man mit memcpy 3 Bytes kopiert (nur Xmega)
- PR52484, PR52507, PR52505: Probleme mit dem 24-Bit Address Space
__memx
- PR51527: Manche binäre Operanden auf __int24 mit Konstanten,
die ausserhalb dem Bereich vom __int24 liegen und nicht auf __int24
gecastet wurden.
- PR53256: Die AVR-Libc enthält Makros für ISR, die Attribut-
Kombinationen verwenden, die nie dokumentiert/spezifiziert waren,
zB eine Funktion gleichzeitig als interrupt und als signal zu
attributieren. Um das zu beheben musste die Semantik von interrupt
und signal im Compiler geändert werden, da es der AVR-Libc nicht
möglich ist, das ISR-Makro anders zu schreiben.
- PR52737: -mtiny-stack wird als Multilib-Option verwendet, was ein
Design-Fehler war. Ab 4.7.1 wird -msp8 als Multilib-Option genommen.
- PR52692: AVR-spezifische Built-Ins funktionieren nicht mit LTO