Forum: Compiler & IDEs fehlende Rechenschritte in listfile aus C


von Nicky (Gast)


Lesenswert?

Hallo Zusammen,

bisher war Assembler meine bevorzugte Variante meine Controller zu 
programmieren. Seit einer Woche "quäle" (aller Anfang ist schwer) ich 
mich mit C (AVR Studio mit WINAVR) herum. Bisher klappte bis auf 
kleinere Anfangschwierigkeiten alles bestens.

Nun wollte ich eine Routine einfügen, doch komischer Weise werden in 
dieser Befehle übersprungen? Das verstehe ich nun überhaupt nicht. Eine 
Fehlermeldung kann ich nicht erkennen.

Hier mal das Fragment:
1
{
2
unsigned int i;
3
4
i= ((ucMaxUserPreset * 4) + ((event_chart[3] - 1) * 65) );
5
                              
6
 /*Wait for completion of previous write */
7
while(EECR & (1<<EEPE));
8
9
/* Set up address register */
10
EEAR   = i;
11
  
12
/* Start eeprom read by writing EERE */
13
EECR   |= (1<<EERE);
14
15
/*unsigned char j;
16
j  = EEDR;
17
j  = (~j);
18
j++;
19
j  = (j / 10);
20
21
SPDR = DISPL_NR_CODE[j];  */
22
23
24
SPDR  = DISPL_NR_CODE[(((~EEDR)+1)/10)];
25
}

In der letzten Zeile kommt nur Käse heraus, dort soll ein Byte aus dem 
EEProm geholtenwerden. Der Wert soll für die 10-er Stelle für eine 7 
Segmentanzeige berechnet und ausgegeben werden. In DISPL_NR_CODE steht 
lediglich die Codierung dafür, diese funktioniert auch in anderen 
Routinen bestens.
Da dies nun nicht funktioniert, habe ich versucht alles in 
Einzelschritten zu machen ( jetzt auskommentierter Teil über der SPDR  = 
- Anweisung) aber dort liesst er nur den Wert aus dem EEPROM, die 
Invertierung, das Increment und die Teilung werden übersprungen (sind im 
Assembler-File oder List-File auch nicht zu finden.

Kann mir hierzu mal jemand einen Tip geben? Ich weiss nicht mehr 
weiter!!!
Vorab schon einmal vielen Dank!!!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ist nicht nachvollziehbar.  Ich habe aus deinem copy&paste-Teil mal
ein Stück in sich compilierfähigen Code gebaut:
1
#include <avr/io.h>
2
3
void readeeprom(uint8_t i, uint8_t j)
4
{
5
 /*Wait for completion of previous write */
6
 while(EECR & (1<<EEPE));
7
8
 /* Set up address register */
9
 EEAR   = i;
10
  
11
 /* Start eeprom read by writing EERE */
12
 EECR   |= (1<<EERE);
13
14
 SPDR = j;  */
15
16
17
 SPDR  = (((~EEDR)+1)/10);
18
}

danach einen ATmega88 als Prozessor erraten und es durch den
Compiler geschickt.  Hier der generierte Assemblercode:
1
.global readeeprom
2
        .type   readeeprom, @function
3
readeeprom:
4
/* prologue: frame size=0 */
5
/* prologue end (size=0) */
6
.L3:
7
        sbic 63-0x20,1
8
        rjmp .L3
9
        clr r25
10
        out (65)+1-0x20,r25
11
        out 65-0x20,r24
12
        sbi 63-0x20,0
13
        in r24,64-0x20
14
        clr r25
15
        ldi r22,lo8(-10)
16
        ldi r23,hi8(-10)
17
        rcall __divmodhi4
18
        out 78-0x20,r22
19
/* epilogue: frame size=0 */
20
        ret
21
/* epilogue end (size=1) */

Die bitweise Negation und anschließende Addition entspricht einer
numerischen Negation.  Die hat der Compiler dadurch ersetzt, dass
er den Divisor der Division von 10 auf -10 geändert hat.  Aber die
Division selbst ist gut zu erkennen.

p.s.: <avr/eeprom.h> kennst du aber, ja?

http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

von Karl H. (kbuchegg)


Lesenswert?

Tu dir selbst einen Gefallen und verwende die fertigen EEPROM Lese 
Funktionen. Jede Wette, dass der Optimizer einen Weg gefunden hat, dass 
sich EEDR seiner Meinung nach nicht verändert, von dort also j immer den 
gleichen Wert erhält und daher der Rest wegfallen kann. Irgendsowas in 
der Richtung

1
#include <avr/eeprom.h>
2
3
...
4
5
void foo()
6
{
7
  unsigned int i;
8
  unsigned char j;
9
10
  i = ((ucMaxUserPreset * 4) + ((event_chart[3] - 1) * 65) );
11
12
  j = eeprom_read_byte( i );
13
14
  SPDR = DISPL_NR_CODE[j];
15
}

Zumindest für gewisse Basisfunktionalität kriegst du vom WinAvr 
Unterstützung. Überflieg das Avr-Gcc-Tutorial um zumindest zu wissen, in 
welchen Bereichen du das Rad nicht neu erfinden musst.

von Nicky (Gast)


Lesenswert?

Hallo und DANKE für die schnelle Antwort, aber so richig verstanden habe 
ich es trotzdem noch nicht, denn im restlichen Code greife ich wie 
beschrieben x mal mit lesen und schreiben so auf den EEprom zu und es 
klappt.

hmmm....

@Jörg Wunsch:
stimmt, es ist ein Mega88 "grübel" und <avr/eeprom.h> schau ich mir 
gleich an :-( obwohl der zugriff auf das eeprom super funktioniert. also 
die daten liesst er bestens aus, nur die wertewandlung dahinter macht 
mir sorgen.

@Karl heinz Buchegger
so einfach geht es leider bei mir nicht. bei mir ist der EEPROM-wert das 
invertierte von dem was ich benötige, einfach weil der eeprom 0xff ab 
werk ist, aber für mich als 0x00 zählt. demnach kann dort später einmal 
ein wert stehen, der invertiert dezimal z.B. 24 ergibt, dieser muss um 1 
erhöht werden und an dieser stelle die 2 für die 10-er stelle ergeben, 
in einem anderen fragment habeich das gleiche problem für die einer 
stelle also nicht i / 10 sondern i % 10 - bisher wie gesagt ging alles 
super - nur hier nicht mehr.


------
ich versteh auchnicht was der gute dort wegoptimieren will, und warum 
erst recht nicht, aber die optimierung ist tatsächlich an. ich glaube 
bis ich das verstehe, werdn noch ein paar wochen ins land gehen.

von Nicky (Gast)


Lesenswert?

Hallo Zusammen,

cih habe es jetzt so gelöst, er kann da scheinbar nichts weg optimieren, 
dafür brauch ich 2 register.

[c]

{
unsigned char j;
unsigned char k;

j  = EEDR;
k  = (~j);
j  = k +1;
k  = (j % 10);
SPDR  = DISPL_NR_CODE[k];
}

und schon bekomme ich das richtige angezeigt!

ich würde aber schon gern wissen, woran das liegt! vielleicht kann sich 
ja jemand erbarmen, denn mit meinen 2 C-Büchern und dem GCC Tutorial 
komm ich da nicht auf einen grünen Zweig.

VG

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ich habe mich erbarmt, und kann dein Problem nicht nachvollziehen,
wie ich oben schon schrieb.

Du musst also wohl oder übel mehr an Details rüberwachsen lassen,
insbesondere:

. eine compilierbare(!) minimale Version des Codes, der das Problem
  verursacht, und

. Informationen über deinen Compiler/deine Umgebung.

von Karl H. (kbuchegg)


Lesenswert?

Nicky wrote:

> so einfach geht es leider bei mir nicht.

Doch, ist es.
Benutz einfach die eeprom_read_byte anstelle das du da selbst was 
erfindest. Zum Beispiel stört mich an deinem Beispiel, dass du zwar das 
Bit setzt um mit dem Lesen anzufangen, aber nicht abwartest, bis das 
EEPROM die Werte rausgesucht hat :-)

> bei mir ist der EEPROM-wert das

> stelle also nicht i / 10 sondern i % 10 - bisher wie gesagt ging alles
> super - nur hier nicht mehr.

Dann rechne eben den Wert aus dem EEPROM entsprechend um.

von Nicky (Gast)


Lesenswert?

@ Karl heinz Buchegger

genau das mache ich doch, die eeprom routine ist exact die aus dem 
datenblatt des mega88. das j = EEDR gibt mir auch den richtigen wert.

aber die 3 anweisungen zwischen j = EEDR und der ausgabe SPDR = .... die 
machen nichts, oder besser gesagt, die gibt es im assebler dann nicht 
mehr und beim single step im c-code sind die auch nur schmuck ohne 
wirkung. :-) also die eepromzurgriffe funktionieren. aber trotzdem lass 
ich mich gern belehren und mich auf optimaler lösungen führen. deshalb 
danke.

€ Jörg Wunsch
ich bastle gerade an einer version, die sich auf das nötigste beschränkt 
und hoffe das dort dann der fehler auch auftritt - kann aber noch ein 
wenig dauern, denn der µC ist breits mit 50% voll und das muss ich ja 
nicht alles mitschicken.

Zu compiler und umgebung:

WinXP, AVR Studio 4.16 build 628 mit WinAVR vom 05.12.2008! controller 
ist ein mega88, clock 20Mhz, Optimierungseinstellung -0s

der rest folgt später!

von Nicky (Gast)


Angehängte Dateien:

Lesenswert?

So, weiter kürzen geht kaum noch, sonst wird es zu undurchsichtig denke 
ich, wird es so schon sein, denn ich lerne noch, also immer ran mit den 
verbesserungsvorschlägen. der fehler tritt in "displ_mux.c" auf, der 
bereicht mit den 3 varianten ist markiert und auch das verhalten steht 
dabei.

ausserdem so ist es in C:
1
unsigned char j;
2
3
j  = EEDR;    // <--- funktioniert
4
              
5
j  = (~j);    // berechnung erfolgt nicht
6
j  = j +1;    // berechnung erfolgt nicht
7
j  = (j % 10);  // berechnung erfolgt nicht
8
              
9
SPDR  = DISPL_NR_CODE[j];  // <--- funktioniert

und dies wird daraus im Disassembler:
1
165:                    EEAR   = i;
2
+000000F6:   BD92        OUT       0x22,R25       Out to I/O location
3
+000000F7:   BD81        OUT       0x21,R24       Out to I/O location
4
168:                    EECR   |= (1<<EERE);
5
+000000F8:   9AF8        SBI       0x1F,0         Set bit in I/O register
6
199:
7
  j  = EEDR;    // <--- funktioniert
8
+000000F9:   B580        IN        R24,0x20       In from I/O location
9
207:
10
  SPDR  = DISPL_NR_CODE[j];  // <--- funktioniert
11
+000000FA:   9581        NEG       R24            Two's complement
12
+000000FB:   E06A        LDI       R22,0x0A       Load immediate
13
+000000FC:   D1D6        RCALL     PC+0x01D7      Relative call subroutine
14
+000000FD:   01FE        MOVW      R30,R28        Copy register pair
15
+000000FE:   0FE9        ADD       R30,R25        Add without carry

und s wie ich das sehe, sind die 3 Anweisungen zwischen
j = EEDR; und SPDR = .....   nicht wirklich vorhanden.

die kurzform als einzeilige anweisung verhält sich gleich!
die lange forn mit j und k variablen funktioniert!

Ich bin ein wenig gespannt, was ich dort versaut habe!?

VG

von Stefan E. (sternst)


Lesenswert?

Nicky wrote:

> und s wie ich das sehe, sind die 3 Anweisungen zwischen
> j = EEDR; und SPDR = .....   nicht wirklich vorhanden.

Sie sind nur als Kommentar nicht vorhanden (weil der Disassembler die 
Zuordnung wohl nicht hin bekommt). Als Assembler-Code sind sie da.

1
j  = (~j);
2
j  = j +1;
 wird zusammen zu
1
+000000FA:   9581        NEG       R24            Two's complement

und
1
j  = (j % 10);
wird zu
1
+000000FB:   E06A        LDI       R22,0x0A       Load immediate
2
+000000FC:   D1D6        RCALL     PC+0x01D7      Relative call subroutine

von Stefan E. (sternst)


Lesenswert?

Noch was:
Wenn ich mir deine Postings so anschaue, dann ist es mal "/10" und mal 
"%10". Könnte das vielleicht der Grund sein, warum es mal geht und mal 
nicht? ;-)

von Nicky (Gast)


Lesenswert?

Hallo Stefan Ernst,

nein, das ich mal / und mal % liegt daran, das ich die gleiche abfolge 
in 2 routinen haben, einmal die 10-stelle und einmal die 1-er stelle 
eines 7 segment display, demnach einmal / 10 und einmal rest (modulo). 
aber trotzdem danke für deine mühe!

hmm, du meinst also im disassembler werden die zuordnungen durcheinander 
gehauen? aber nichts desto trotz kam trotzdem müll bei der berechnung 
heraus - ich hab es ja auch auf dem display sehen können und im single 
step in C werden die zeilen auch gnadenlos übersprungen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nicky wrote:

> genau das mache ich doch, die eeprom routine ist exact die aus dem
> datenblatt des mega88.

Karl Heinz hatte dir allerdings (genau wie ich schon weiter oben)
nahe gelegt, dass du stattdessen die Routinen aus der avr-libc
(aus <avr/eeprom.h>) benutzt.

Ansonsten hast du 1.) nach wie vor noch kein compilierbares
Beispiel geliefert (ich möchte mir gern den Assemblercode angucken,
den mein Compiler draus macht, nicht den blöden Disassembler vom
AVR Studio mit seinen unsinnigen Kommentaren und fehlenden symbolischen
Adressen), zweitens hat dein Disassembler-Listing aber trotzdem
gezeigt, dass beide Rechenoperationen da sind -- auch wenn der
Compiler die Rechnung anders gelöst hat als du.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nicky wrote:

> aber nichts desto trotz kam trotzdem müll bei der berechnung
> heraus

Dann solltest du wohl als nächstes erst einmal überdenken, ob denn
dein Algorithmus überhaupt hinhaut...

von Stefan E. (sternst)


Lesenswert?

Nicky wrote:

> und im single
> step in C werden die zeilen auch gnadenlos übersprungen.

Ja, logisch, weil, wie gesagt, der Disassembler den C-Code nicht dem 
Assembler-Code zuordnen kann.

> aber nichts desto trotz kam trotzdem müll bei der berechnung
> heraus - ich hab es ja auch auf dem display sehen können

Der Assembler-Code entspricht jedenfalls deinen C-Vorgaben.

von Nicky (Gast)


Lesenswert?

@Jörg Wunsch

ich hab ja eine losung, mit 2 variablen geht es ja, nur würde mich 
interessieen, warum es nicht mit einer klappt - ist halt reines 
interesse, und vielleicht gibt es einen guten grund. mit j und k ist ja 
alles prima, ich hatte mich nur dran gewöhnt, alles in eine anweisung zu 
packen. im endeffekt ändert sich ja an der abarbeitung nicht wirklich 
viel - denn diese routine wird nur bei einem tastendruck durchlaufen und 
nicht ständig.

aber aus fehlern lernt man - und wenn es einer ist, wüsste ich schon 
gern wo er steckt.

trotzdem allen vielen dank!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Nicky wrote:

> ich hab ja eine losung, mit 2 variablen geht es ja, nur würde mich
> interessieen, warum es nicht mit einer klappt - ist halt reines
> interesse, und vielleicht gibt es einen guten grund. mit j und k ist ja
> alles prima, ich hatte mich nur dran gewöhnt, alles in eine anweisung zu
> packen. im endeffekt ändert sich ja an der abarbeitung nicht wirklich
> viel - denn diese routine wird nur bei einem tastendruck durchlaufen und
> nicht ständig.

Alles in eine Anweiung zu packen ist kein Problem, und oben seh ich 
nirgends einen falschen Code.

> aber aus fehlern lernt man - und wenn es einer ist, wüsste ich schon
> gern wo er steckt.

Hier würde ein kleiner Testfall helfen, d.h. ein Stück Code, der sich 
ohne Compiler-Fehler compilieren lässt.

Bei deinem obigen Code kommt zB ein
1
foo.c: In function 'foo':
2
foo.c:12: error: 'DISPL_NR_CODE' undeclared (first use in this function)
nachdem man das ganze in ne Funktion gepackt hat.

Geht man von folgenden Testfällen aus
1
#include <avr/io.h>
2
3
extern unsigned char DISPL_NR_CODE[];
4
5
void foo1 ()
6
{
7
    unsigned char j;
8
    unsigned char k;
9
10
    j  = EEDR;
11
    k  = (~j);
12
    j  = k +1;
13
    k  = (j % 10);
14
    SPDR  = DISPL_NR_CODE[k];
15
}
16
17
void foo2 ()
18
{
19
    SPDR  = DISPL_NR_CODE[((~EEDR)+1) % 10];
20
}

dann ergibt sich i.W. folgendes Kompilat (mit -S)
1
foo1:
2
  in r24,64-32
3
  neg r24
4
  ldi r22,lo8(10)
5
  rcall __udivmodqi4
6
  ldi r30,lo8(DISPL_NR_CODE)
7
  ldi r31,hi8(DISPL_NR_CODE)
8
  add r30,r25
9
  adc r31,__zero_reg__
10
  ld r24,Z
11
  out 78-32,r24
12
  ret
13
14
foo2:
15
  in r24,64-32
16
  ldi r25,lo8(0)
17
  com r25
18
  neg r24
19
  sbci r25,lo8(-1)
20
  ldi r22,lo8(10)
21
  ldi r23,hi8(10)
22
  rcall __divmodhi4
23
  movw r30,r24
24
  subi r30,lo8(-(DISPL_NR_CODE))
25
  sbci r31,hi8(-(DISPL_NR_CODE))
26
  ld r24,Z
27
  out 78-32,r24
28
  ret

Die zweite Version unterscheidet sich von der ersten durch einen 
(impliziten) Cast aufgrund des C Sprachstandards. Vielleicht liegt darin 
ein Problem, daß einmal mit 8 Bit gerechnet wird und einmal mit 16 Bit?

Optionen waren:
1
 ;  GNU C (WinAVR 20090313) version 4.3.2 (avr)
2
 ;   compiled by GNU C version 3.4.5 (mingw-vista special r3), GMP version 4.2.3, MPFR version 2.4.0.
3
 ;  GGC heuristics: --param ggc-min-expand=47 --param ggc-min-heapsize=32702
4
 ;  options passed:  -fpreprocessed foo.i -mmcu=atmega88 -Os 
5
 ;  -std=gnu99 -fverbose-asm -fpack-struct -fno-reorder-functions
6
 ;  -fno-builtin -fno-keep-inline-functions -fno-common
7
 ;  -fno-inline-small-functions -fno-tree-scev-cprop

Johann

von Karl H. (kbuchegg)


Lesenswert?

Nicky wrote:
> @ Karl heinz Buchegger
>
> genau das mache ich doch,

Wo machst du das?

Dein Code in Pseudocode

    Warte bis das EEPROM eine mglw. vorhergehende Operation
    abgeschlossen hat

    Stell die Adresse ein

    Gib den Lesebefehl

    Hol den Wert aus dem EEDR Register


Wo wartest du nach dem geben des Lesebefehls, das der angeforderte Wert 
tatsächlich im EEDR Register angekommen ist?

von Stefan E. (sternst)


Lesenswert?

Karl heinz Buchegger wrote:

> Wo wartest du nach dem geben des Lesebefehls, das der angeforderte Wert
> tatsächlich im EEDR Register angekommen ist?

Man muss nicht warten.

Datenblatt:
1
The EEPROM Read Enable Signal EERE is the read strobe to the EEPROM.
2
When the correct address is set up in the EEAR Register, the EERE bit
3
must be written to a logic one to trigger the EEPROM read.
4
The EEPROM read access takes one instruction, and the requested data is
5
available immediately. When the EEPROM is read, the CPU is halted for four
6
cycles before the next instruction is executed.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst wrote:
> Karl heinz Buchegger wrote:
>
>> Wo wartest du nach dem geben des Lesebefehls, das der angeforderte Wert
>> tatsächlich im EEDR Register angekommen ist?
>
> Man muss nicht warten.

Ehrlich?

[Datenblatt rauskram, Tutorial rauskram]

tatsächlich!

Bin schon still. War ein Fehler meinerseits.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. wrote:

> Die zweite Version unterscheidet sich von der ersten durch einen
> (impliziten) Cast aufgrund des C Sprachstandards. Vielleicht liegt darin
> ein Problem, daß einmal mit 8 Bit gerechnet wird und einmal mit 16 Bit?

Ja, den Eindruck habe ich mittlerweile auch.

Wenn ich den Ausdruck
1
(((~EEDR)+1)/10)

umschreibe in
1
((uint8_t)((~EEDR)+1)/10)

dann bekomme ich den exakt gleichen Assemblercode wie für die Variante
mit den zwei zusätzlichen Variablen.  Die Benutzung der Zwischen-
variablen wirkt wie ein typecast auf (uint8_t) für die einzelnen
Teilschritte.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:
> Johann L. wrote:
>
>> Die zweite Version unterscheidet sich von der ersten durch einen
>> (impliziten) Cast aufgrund des C Sprachstandards. Vielleicht liegt darin
>> ein Problem, daß einmal mit 8 Bit gerechnet wird und einmal mit 16 Bit?
>
> Ja, den Eindruck habe ich mittlerweile auch.

Möglicherweise wegen des sign-extend? Damit landen Zwischenwerte > 127 
im Nirvana...

Johann

von Stefan E. (sternst)


Lesenswert?

> ... (impliziten) Cast ... sign-extend ...

Ich möchte bei diesen Überlegungen nur zu bedenken geben, dass der 
Mehrzeiler mit einer Variablen ja angeblich auch nicht funktionieren 
soll.

von Nicky (Gast)


Lesenswert?

@Karl heinz Buchegger Datum: 16.03.2009 21:27

------------------------------------------------------------------------ 
--------
Nicky wrote:
> @ Karl heinz Buchegger
>
> genau das mache ich doch,


>@ Karl heinz Buchegger
>Wo machst du das?

>Dein Code in Pseudocode

>    Warte bis das EEPROM eine mglw. vorhergehende Operation
>    abgeschlossen hat
1
/* Wait for completion of previous write */
2
while(EECR & (1<<EEPE));

>    Stell die Adresse ein
1
/* Set up address register */
2
EEAR = i;

>    Gib den Lesebefehl
1
/* Start eeprom read by writing EERE */
2
EECR |= (1<<EERE);

>    Hol den Wert aus dem EEDR Register
1
j  = EEDR;

>Wo wartest du nach dem geben des Lesebefehls, das der angeforderte Wert
>tatsächlich im EEDR Register angekommen ist?

Der Wert steht nach
1
 EECR |= (1<<EERE);
 nach 4 Takten im EEDR, im Disassembler dauert es auch tasächlich so 
lange, bis er die folgenden Schritte durchführt.

> Auszug aus dem Datenblatt des Mega88 Seite 18:
When the EEPROM is read, the CPU is halted for four clock cycles before 
the next instruction is
executed.

Zumal ich noch einmal betonen möchte, es wird der richtige Wert 
ausgelesen!!! und dies x-fach auch in anderen Abschnitten nach gleichem 
Schema. Es mag vielleicht nicht sonderlich Schick sein, o.k. und ich 
gelobe mich zu bessern, wenn ich verstanden habe warum. Aber das EEprom 
lesen und schreiben macht mir keinerlei sorgen.

von Nicky (Gast)


Lesenswert?

@ Johann L. , @ Jörg Wunsch & @Stefan Ernst

>impliziter Cast ???


Cast-Operator habe ich schonmal gehört. hmmm
ok, ich werd mal schauen was ich dazu finde --> momentan versteh ich nur 
bahnhof.

Danke euch allen!

von Nicky (Gast)


Lesenswert?

impliziter Cast?

typumwandlung während der berechnung - hab ich es richtig?

wenn ja nur wo und warum?

ich lese aus dem eeprom

>0xFF

da dies bei mir 0 entspricht --> complement bilden, aber dabei sollte 
unsingned char doch auch dies bleiben?

jetzt sollte also aus 0xFF

>0x00 -> geworden sein

dann 0x00 + 1 weil ich den folgenden Step benötige dort sehe ich 
eigentlich auch keinen Grund für eine typumwandlung.

>0x01

und davon bilde ich division durch 10 und im andere Teil rest von der 
Division

-> also
1
/10
 = 0
-->
1
%10
 = 1

da ich j als unsigned char und nicht als signed verwende - versteh ich 
also nicht, wo da eine typumwandlung stattfinden soll.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nicky wrote:

> ich lese aus dem eeprom
>
>>0xFF
>
> da dies bei mir 0 entspricht

Nun, es ist aber hier 255, d. h. durch die Umwandlung nach Typ
int (die implizit durch C vorgegeben ist), wird daraus ein 0x00FF.

Das negierst du bitweise, also 0xFF00.  Danach addierst du 1, also
0xFF01.  Das ist das Bitmuster der Zahl -255.  Die teilst du durch
10, das ergibt eine -25, oder 0xFFE7.  Davon nimmst du das untere
Byte, also 0xE7, oder 231, wenn man es als uint8_t betrachtet.

Was du dagegen willst ist, dass aus der 0xFF eine 0x00 wird, zu
dieser 1 addiert (=> 0x01), und durch 10 dividiert, ergibt 0.

> da ich j als unsigned char und nicht als signed verwende - versteh ich
> also nicht, wo da eine typumwandlung stattfinden soll.

Weil C immer wenigstens im Bereich `int' rechnet.

Den Typecast, den du brauchst, habe ich dir oben schon gezeigt:

Beitrag "Re: fehlende Rechenschritte in listfile aus C"

von Nicky C. (nicky)


Lesenswert?

Jörg Wunsch wrote:

> Weil C immer wenigstens im Bereich `int' rechnet.

Na das ist doch eine Aussage - die verstehe sogar ich und verstehe dann 
auch, warum da Käse herauskommen muss! Ich wusste dies nicht und werd es 
gleich mal ausprobieren. Ich wollte zwar
1
#include <stdint.h>

nicht verwenden, aber dann werde ich mal einiges ändern.

Ich hoffe es funktioniert dann und bedanke mich für die Erklärung und 
eure Mühen!

Ich hoffe ich kann mich mal wieder revanchieren, zwar sicher nicht in 
naher Zukunft bei GCC aber viellecht im Elektronikteil.

VG

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
Noch kein Account? Hier anmelden.