www.mikrocontroller.net

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


Autor: cerberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: cerberus (Gast)
Datum:

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

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: cerberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: cerberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Volkmar (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: cerberus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bei näherem Überlegen hast Du Recht...

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Detlef (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm 'ne union.

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.