Forum: Compiler & IDEs 4-Byte zu 1-Byte


von cerberus (Gast)


Lesenswert?

Hi.
Eine kurze Frage die bestimmt schon 100Mal diskutiert wurde, aber ich
find sie nicht.
Ich habe eine beliebig große Zahl z.B. 357913941  und möchte sie
Byteweise in den Output schreiben.

Zur Zeit sieht das so aus:

PORTA = (Zahl);
PORTB = (Zahl>>8);
PORTC = (Zahl>>8);
PORTD = (Zahl>>8);


Es funktioniert, aber der Compiler meckert mit Warnings rum, weil die
Zahl über ihr Ende hinaus verschoben wird.
Wie wird das besser gemacht, so dass der Compiler GCC nicht meckert?

von Rufus T. Firefly (Gast)


Lesenswert?

PORTA = (Zahl);
PORTB = (Zahl>>8);
PORTC = (Zahl>>8);
PORTD = (Zahl>>8);


Das funktioniert nicht wirklich; den Ports B bis D wird exakt der selbe
Wert zugewiesen.

Die Warnung des Compilers besagt auch nicht, daß die Zahl "über ihr
Ende hinaus verschoben" würde, sondern daß der Wertebereich der
Variablen PORTA..D für die Zuweisung zu klein ist.

Besser wirds mit

PORTA = (uint8_t) (Zahl & 0xFF);
PORTB = (uint8_t) ((Zahl >> 8) & 0xFF);
PORTC = (uint8_t) ((Zahl >> 16) & 0xFF);
PORTD = (uint8_t) ((Zahl >> 24) & 0xFF);

von cerberus (Gast)


Lesenswert?

>>8, >>16 ist natürlich richtig, ... sorry
aber was macht "& 0xFF" ?

von Daniel (Gast)


Lesenswert?

Hallo,

"&0xFF" bewirkt, dass nur die niedrigsten 8 bit (also das
niederwertigste Byte) ins Ergebnis kommen, alle anderen werden
ausgeblendet.

IMHO ist das eigentlich überflüssig bei AVR-GCC (oder prinzipiell ?),
da der Cast auf uint8_t eh nur die niedrigsten 8 bit berücksichtigt. Es
könnte ja aber Compiler geben, die dann Aufrunden (ich kenn das nur von
Matlab). Rufus möge mich klorrigieren, wenn's nicht stimmt ;-).

MfG, Daniel

von cerberus (Gast)


Lesenswert?

...
ach ja, muss ich nochwas beachten?

main.c:93: warning: right shift count >= width of type
main.c:97: warning: right shift count >= width of type
main.c:109: warning: right shift count >= width of type
main.c: In function `main':
main.c:139: warning: overflow in implicit constant conversion
main.c:140: warning: overflow in implicit constant conversion
main.c:141: warning: overflow in implicit constant conversion
main.c:142: warning: overflow in implicit constant conversion
main.c:163: warning: overflow in implicit constant conversion
main.c:177: warning: overflow in implicit constant conversion
main.c:192: warning: overflow in implicit constant conversion
main.c:206: warning: overflow in implicit constant conversion

von Rufus T. Firefly (Gast)


Lesenswert?

Sieht so aus.

Den Sourcecode, der diese Meldungen erzeugt, solltest Du posten (die
betreffenden Zeilen und die Stellen, an denen die verwendeten
Variablen/Konstanten deklariert werden, sollten genügen), dann kann man
Dir genau sagen, was schiefgeht.

von cerberus (Gast)


Lesenswert?

void send_Ports (char numdat, int start, int ende)
{
PORTE = (numdat);
PORTA = (uint8_t) (start<<3) & 0xFF);
PORTB = (uint8_t) (start>>5) & 0xFF);
PORTC = (uint8_t) (start>>13) & 0xFF);
PORTD = (uint8_t) (start>>21) & 0xFF);
PORTA = (uint8_t) (ende<<3) & 0xFF);
PORTB = (uint8_t) (ende>>5) & 0xFF);
PORTC = (uint8_t) (ende>>13) & 0xFF);
PORTD = (uint8_t) (ende>>21) & 0xFF);
}


lichtan();
display_cursor(1,1);
display_string("Hallo ");
send_Ports(0,8192,536862720);
send_Ports(1,16384,536862720);
send_Ports(2,24576,536862720);
send_Ports(3,32768,536862720);

von Volkmar (Gast)


Lesenswert?

Du hast die Variablen start und ende als int deklariert. Damit ist der
Wertebereich -32768..32767. Du mußt long nehmen, wenn Du so große
Zahlen bearbeiten willst.

Volkmar

von cerberus (Gast)


Lesenswert?

bei näherem Überlegen hast Du Recht...

von Rufus T. Firefly (Gast)


Lesenswert?

... außerdem fehlen im Sourcecode Klammern; ich kann mir nicht
vorstellen, daß der Compiler diese Zeilen

  PORTA = (uint8_t) (start<<3) & 0xFF);
  ... etc
  PORTD = (uint8_t) (ende>>21) & 0xFF);

ohne Genörgel übersetzt.

Die fehlende Klammer ist jeweils vor 'ende' einzufügen.

von sven (Gast)


Lesenswert?

unsigned char tmp1, tmp2, tmp3, tmp4;
        unsigned long tmp; //---> dein longwert

  asm volatile(
    "mov  %0, %A2    \n\t"
    "mov  %1, %B2    \n\t"
    "mov  %2, %C2    \n\t"
    "mov  %3, %D2    \n\t"
    : "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4),
    : "r"(tmp)
    );
                // tmp1 = das niederwertigste byte des long
                // tmp4 = da höchstwertige...

        PORTA = tmp1;
        PORTB = tmp2;
        PORTC = tmp3;
        PORTD = tmp4;

---> der speicherschonenste weg :-)

von sven (Gast)


Lesenswert?

der fehlerteufel!!!!

asm volatile(
    "mov  %0, %A4    \n\t"
    "mov  %1, %B4    \n\t"
    "mov  %2, %C4    \n\t"
    "mov  %3, %D4    \n\t"
    : "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
    : "r"(tmp)
    );

^^^^so muss des aussehen :-)

von Detlef (Gast)


Lesenswert?

Hallo,

danke für den Code, hilft sehr. Aber wie greift man denn auf die
Einzelbytes zu, wenn (tmp) vom (avr-) Typ 'long long' ist, also 8
Byte. Nicht mit %E4 usw, das haut nicht hin !?

Danke
Detlef

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


Lesenswert?

Nimm 'ne union.

union {
  uint32_t l;
  uint8_t c[4];
} ...;

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.