4-Byte zu 1-Byte

Gast #236786
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?
Gast #236787
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);
Gast #236789
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
Gast #236790
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
Gast #236791
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.
Gast #236792
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);
Gast #236795
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.
Gast #236796
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 :-)
Gast #236797
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 :-)
Gast #236798
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren