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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.