Forum: Compiler & IDEs 16Bit Zahl in 2 8 Bit zahlen teilen


von Michl (Gast)


Lesenswert?

Hy Leute!

Hab mal ne kurze Frage an euch. Ich hab ne Zahl wie zB.: 180 und die 
muss in zwei 8Bit Variablen reingeschrieben werden. (Anwendung: Timer 1 
- High und Low). Kann mir vl irgendwer sagen obs da ne Funktion gibt, 
die mir das umrechent oder muss ich mir das mühsam berechnen (immer /2 
und schaun ob ein Rest bleibt)?

Danke im Voraus!

von Thomas (Gast)


Lesenswert?

uint8_t HighByte = (180 >> 8);
uint8_t LowByte = 180 & 0xFF;

von Sardaukar (Gast)


Lesenswert?

Wenn Du Deine 180 bereits im Speicher liegen hast (z.B. als unsigned 
short), dann erledigt das der Compiler für Dich:

unsigned short a = 180;

unsigned char lo, hi;

lo = ( unsigned char )a;
hi = *( ( unsigned char* )a + 1 );

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Sardaukar wrote:
> Wenn Du Deine 180 bereits im Speicher liegen hast (z.B. als unsigned
> short), dann erledigt das der Compiler für Dich:
>
> unsigned short a = 180;
>
> unsigned char lo, hi;
>
> lo = ( unsigned char )a;
> hi = *( ( unsigned char* )a + 1 );

Ja, bei Little Endian Maschinen ist das so.
http://de.wikipedia.org/wiki/Byte-Reihenfolge

von Uhu U. (uhu)


Lesenswert?

Sowas erledigt man am besten mit zwei Macros in einem Headerfile:

   #define LOW_BYTE(x)        (x & 0xff)
   #define HIGH_BYTE(x)       ((x >> 8) & 0xff)

Dann ist der Code portabel.

von Jörg X. (Gast)


Lesenswert?

Oder du benutzt gleich die 16-Bit Register (von Timer oder ADC) als 
solche:
1
uint16_t value = 902;
2
OCR1 = value;
3
ICR1 = value;
4
value = ADC; //ADCW ginge auch
5
UBRR = value;
6
/* etc.*/
hth. Jörg

von yalu (Gast)


Lesenswert?

> hi = *( ( unsigned char* )a + 1 );

Da ist ein & verloren gegangen:

  hi = *( ( unsigned char* )&a + 1 );

Ansonsten würde ich aber, wo dies möglich ist, Jörgs Weg mit den
16-Bit-Zugriffen bevorzugen: Sieht am maximal gut aus, ist maximal
kurz und liefert in allen Kontexten maximal effizienten Code.

von Simon K. (simon) Benutzerseite


Lesenswert?

yalu wrote:
>> hi = *( ( unsigned char* )a + 1 );
>
> Da ist ein & verloren gegangen:
>
>   hi = *( ( unsigned char* )&a + 1 );
>
> Ansonsten würde ich aber, wo dies möglich ist, Jörgs Weg mit den
> 16-Bit-Zugriffen bevorzugen: Sieht am maximal gut aus, ist maximal
> kurz und liefert in allen Kontexten maximal effizienten Code.

Komisch, letztens ging das nicht mit dem UBBR Register vom UART bei mir. 
(Aktuelle WinAVR Version)

Hängt das vielleicht mit dem URSEL Bit zusammen?

von Johannes M. (johnny-m)


Lesenswert?

Simon Küppers wrote:
> Komisch, letztens ging das nicht mit dem UBBR Register vom UART bei mir.
> (Aktuelle WinAVR Version)
>
> Hängt das vielleicht mit dem URSEL Bit zusammen?
Das URSEL-Bit gibts ja nur bei einigen wenigen AVRs (Mega16 und 
verwandte). Da muss man natürlich ein bisschen aufpassen und 
sicherstellen, dass das URSEL auch wirklich 0 ist. Bei den anderen AVRs 
sollte das aber unproblematisch sein.

von Simon K. (simon) Benutzerseite


Lesenswert?

Johannes M. wrote:
> Simon Küppers wrote:
>> Komisch, letztens ging das nicht mit dem UBBR Register vom UART bei mir.
>> (Aktuelle WinAVR Version)
>>
>> Hängt das vielleicht mit dem URSEL Bit zusammen?
> Das URSEL-Bit gibts ja nur bei einigen wenigen AVRs (Mega16 und
> verwandte). Da muss man natürlich ein bisschen aufpassen und
> sicherstellen, dass das URSEL auch wirklich 0 ist. Bei den anderen AVRs
> sollte das aber unproblematisch sein.

Ja, um den Mega16 geht's. Problem: UBRR ist nicht definiert. includet 
habe ich <avr/io.h>
UBRRH und UBRRL hingegen gab es.

von Johannes M. (johnny-m)


Lesenswert?

Simon Küppers wrote:
> Ja, um den Mega16 geht's. Problem: UBRR ist nicht definiert. includet
> habe ich <avr/io.h>
> UBRRH und UBRRL hingegen gab es.
Hmm, ist mir bisher nie aufgefallen. Aber ist zumindest nachvollziehbar, 
dass es tatsächlich am URSEL (oder an der Ursel;-?) liegt.

von Jörg X. (Gast)


Lesenswert?

sry, falls ich Verwirrung gestiftet hab ;)
Das UBRR kann man scheinbar nur auf wenigen AVRs als 16Bit-register 
benutzen (scheinbar nur auf neueren Atmegas, neuer als z.B. die 
mega16/32)
Das ist aber auch nicht so tragisch, da beim UBRR die Reihenfolge der 
Zugriffe keine Rolle spielt! (und  UBRRH i.d.R. mit 0 vorbelegt  ist).

hth. Jörg

von Simon K. (simon) Benutzerseite


Lesenswert?

Jörg X. wrote:
> sry, falls ich Verwirrung gestiftet hab ;)
> Das UBRR kann man scheinbar nur auf wenigen AVRs als 16Bit-register
> benutzen (scheinbar nur auf neueren Atmegas, neuer als z.B. die
> mega16/32)
> Das ist aber auch nicht so tragisch, da beim UBRR die Reihenfolge der
> Zugriffe keine Rolle spielt! (und  UBRRH i.d.R. mit 0 vorbelegt  ist).
>
> hth. Jörg

Bei der Initialisierung hat das keinen Effekt, sehe ich auch so. Dennoch 
steht im Datenblatt:

> Writing UBRRL will trigger an immediate update of
> the baud rate prescaler.

Sprich: UBRRL forciert während einer laufenden Transmission das Update 
der Baudrate.
Erledigt man das aber im Voraus ist das wohl egal, da es hier nicht 
dieses "Buffer"-prinzip gibt, wie zum Beispiel beim Timer. (Erst Low 
bzw. High Register laden, das landet dann in einem Temporärregister. 
Nach dem Laden des High bzw. Low Registers werden dann der Wert dieses 
mit dem Wert im Temporärregister auf einen Schlag geladen). Und das ist 
vermutlich das, was du meintest :-)

von Jörg X. (Gast)


Lesenswert?

@simon:
Ja, das meinte ich.
>> Writing UBRRL will trigger an immediate update of
>> the baud rate prescaler.
Das hab ich zum ersten mal gesehen :(  -- da muss man ja doch aufpassen.

thx. Jörg

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.