Forum: Compiler & IDEs 8 Bit aus 32-Bit-Variable auswählen


von M. S. (elpaco)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem:

Ein DDS erhält ein 16-Bit-Paket Daten per SPI, um die Frequenzregister 
zu beschreiben. Davon sind 8 Bit Kommando+Adresse des Frequenzregisters, 
8 Bit Daten.

Das Frequenzregister setzt sich insgesamt aus 32 Bit zusammen. Somit 
habe ich vier aufeinanderfolgende Datenpakete vom µC an den DDS; Diese 
enthalten jeweils 8 Bit des Frequenzregisters.

Innerhalb des µC stehe ich nun vor der Herausforderung, das Datenpaket 
zusammenzupuzzeln. Die Zahl, die ich in das Frequenzregister schreiben 
will, ist 32 Bit lang. Es wird das LSB zuerst geschrieben.

Folgendes muss also realisiert werden:
Datenpaket 1 = 8 Bit Befehl+Adresse (fix) + unterste 8 Bit aus dem 
32-Bit Register für die Frequenz (variabel)

Datenpakete 2 bis 4 analog.

Meine Fragen dazu:

Wie wähle ich aus den 32 Bit genau 8 Bit aus?

Und wie setze ich die dann hinter die ersten 8 Bit die den 
Befehl+Adresse enthalten?
1
Frequenz<<=8;
2
uint16_t Datenpaket = 0bxxxxxxxx00000000|Frequenz;

Das Ganze eben viermal?

: Bearbeitet durch User
von Uwe S. (de0508)


Lesenswert?

Hallo,

ich verstehe die Fragestellung nicht. Bitte mache mal ein Bild des 
Datenpakets und dessen Bedeutung.

Bitte beschreibe die Anwendung / Fragestellung nicht deine Umsetzung.

Vielleicht kennst Du schon das Schlüsselwort UNION ?

https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html

von Helmut L. (helmi1)


Lesenswert?

Mittels einer union kannst du das machen

typedef union {
 unsigned long l;
 unsigned char b[4];
} L_B;


L_B   lb;

lb.l =  32bit
lb.b[0]    byte 0
lb.b[1]    byte 1
lb.b[2]    byte 2
lb.b[3]    byte 3

von M. S. (elpaco)


Lesenswert?

Hallo Uwe,

also wie gesagt habe ich intern im µC eine 32-Bit-Variable, welche eine 
Frequenz enthält, die an einen DDS gesendet werden soll. Diese berechnet 
sich zu

Der µC kommuniziert per SPI mit dem DDS und übergibt ein Wort, also 16 
Bit. Dieses setzt sich in diesem Fall zusammen (MSB:LSB):
Kommandobit 15:12, Adressbit 11:8, Datenbit 7:0.

Es müssen insgesamt also vier solcher Worte gesendet werden, die jeweils 
8 Datenbits aus dem im µC gespeicherten 32-Bit-Wert für die Frequenz 
enthalten - angefangen mit den untersten 8.

Die Frage ist jetzt, wie ich dieses Wort also zusammenpuzzle. Oder 
konkret, ob das mit obigem Code funktionieren kann.

Auf "union" bin ich hier per Foren-Suche gestoßen, dachte aber, dass es 
eventuell auch einfacher gehen könnte. Zeitkritisch ist die Anwendung 
nicht, es soll ein einfacher Frequenzgenerator werden. Ob der jetzt ein 
paar µs früher oder später nach dem Einstellen der Frequenz seine 
Ausgabe ändert ist nicht relevant.

: Bearbeitet durch User
von M.O. (Gast)


Lesenswert?

M. S. schrieb:
> Auf "union" bin ich hier per Foren-Suche gestoßen, dachte aber, dass es
> eventuell auch einfacher gehen könnte.

Die Verwndung von Union setzt allerdings voraus, dass du Vorwissen 
über die Byereihenfolge in long nutzt, d.h. das ist nicht unbedingt 
portabel

von Axel S. (a-za-z0-9)


Lesenswert?

Was für albernes Geschwafel meine Vorredner hier absondern.

Das sind ganz normale arithmetische und logische Operationen. Um aus 
einem 32-bit Integer z.B. die niederwertigsten 8 Bit zu extrahieren, 
verwendet man den & (UND) Operator:
1
uint32_t x;
2
...
3
uint8_t y= x & 0xFF;

Und wenn man statt der niederwertigsten andere 8 Bit haben will, dann 
schiebt man die 32 Bit halt erst so weit nach rechts, bis die 
gewünschten Bits die niederwertigsten sind:
1
uint32_t x;
2
...
3
uint8_t y = (x>>12) & 0xFF;

Und zum Zusammenbauen langer Werte aus kürzeren verwendet man den | 
(ODER) Operator und Schiebeoperationen. Dabei muß man aber aufpassen, 
daß man Zwischenergebnisse erst auf den langen Typ castet. Sonst schiebt 
man die Bits aus dem kurzen Typ hinaus ins Nirvana.

Um z.B. die höchstwertigen 8 Bit in einem 32-bit Wert aus einem 8-bit 
Wert zu setzen (es wird erwartet, daß die vorher 0 sind):
1
uint8_t x;
2
uint32_t y;
3
...
4
y |= ((uint32_t)x << 24);

Ob das nachher richtige Schiebeoperationen werden oder ob die CPU auf 
einzelne Bytes von langen Operanden direkt zugreift, ist eine 
Optimierung die man getrost dem C-Compiler überlassen kann.


XL

von Uwe S. (de0508)


Lesenswert?

Hallo  M. S. ,

welcher DDS ist das nun genau ?

Ich habe schon verschieden Libs für AD9951, AD9851 (AD9850), AD9834 
geschrieben und kann mich in deinen evtl. Einlesen.

von ms (Gast)


Lesenswert?

Hallo,

Danke für eure Antworten! Genau eine solche Lösung mit den 
Bitoperationen habe ich bevorzugt gesucht!

@Uwe: Ich verwende einen AD9835. Die Kommunikation mit dem Chip 
funktioniert soweit per Software-SPI (habe bereits ein paar feste 
Frequenzen testweise erzeugt), momentan kommt der Schritt, bei dem 
mittels ATtiny 2313, Drehgeber und LCD-Display zunächst mal die Frequenz 
eingestellt werden soll. Bis auf das oben dargestellte Problem, welches 
jetzt gelöst ist, denke ich bisher alles verstanden zu haben. Da ich 
aber noch sehr am Anfang stehe, habe ich bisher noch keinen großen Code. 
Werde mich aber gerne an dich wenden, wenn noch weitere Unklarheiten 
aufkommen bzw. den fertigen Code dann hier rein stellen.

von Schwimmbadpinkler (Gast)


Lesenswert?

Hi, habe solches nachdem du fragst oft gemacht:
1
spi_send(Word >> 24);
2
spi_send(Word >> 16);
3
spi_send(Word >>  8);
4
spi_send(Word >>  0);

von Schwimmbadpinkler (Gast)


Lesenswert?

1
uint32_t Word;
2
3
4
void spi_send(uint8_t);

von Schwimmbadpinkler (Gast)


Lesenswert?

Der Compiler versteht was ich will wenn die Optimierung eingeschaltet 
ist. Dann ist der Code kompakter als Assembler!

von Uwe S. (de0508)


Lesenswert?

Hallo  M. S.,

noch eine Frage: auf welchem Board/ Platine sitzt der AD9835, bzw. hast 
Du einen Schaltplan, Bilder davon ?


ms schrieb:
> Hallo,
>
> Danke für eure Antworten! Genau eine solche Lösung mit den
> Bitoperationen habe ich bevorzugt gesucht!
>
> @Uwe: Ich verwende einen AD9835. Die Kommunikation mit dem Chip
> funktioniert soweit per Software-SPI (habe bereits ein paar feste
> Frequenzen testweise erzeugt), momentan kommt der Schritt, bei dem
> mittels ATtiny 2313, Drehgeber und LCD-Display zunächst mal die Frequenz
> eingestellt werden soll. Bis auf das oben dargestellte Problem, welches
> jetzt gelöst ist, denke ich bisher alles verstanden zu haben. Da ich
> aber noch sehr am Anfang stehe, habe ich bisher noch keinen großen Code.
> Werde mich aber gerne an dich wenden, wenn noch weitere Unklarheiten
> aufkommen bzw. den fertigen Code dann hier rein stellen.

von ms (Gast)


Lesenswert?

Hallo Uwe,

Noch sitzt er auf einer tssop-to-dip Platine auf dem Steckbrett. Ob ich 
die fertige Schaltung später auf lochraster löte oder eine Platine ätzen 
lasse ist noch unsicher. Bilder kann ich leider erst am Freitag posten, 
da ich bis dahin unterwegs bin.

von Uwe S. (de0508)


Lesenswert?

Hallo M. S.,

für welchen Ausgabe Frequenzbereich willst Du den AD9835 einsetzen und 
welche Freuquenz hat der ext. Quarzoszillator als Taktquelle?

Wie sieht es mit einem Ausgangsfilter aus? Was ist da geplant ?

von M. S. (elpaco)


Lesenswert?

Hallo Uwe,

ich wollte damit ein paar Versuche zu RFID und Resonanzspulen machen, 
bereich 100 kHz bis <1MHz. Bislang hängt ein 16 MHz-Oszillator dran, der 
AD9835 kann aber bis 50 MHz. Von daher kann es sein, dass ich da noch 
erweitere. Besonders kritisch ist die Auflösung nicht. Ich möchte die 
Frequenz in 1-Hz-Schritten einstellen, die Auflösung bei 50 MHz wäre da 
immernoch deutlich feiner als die 1-Hz-Schritte.

Da ich noch neu auf dem HF-Gebiet bin, habe ich noch keine konkrete 
Vorstellung, wie der Ausgangsfilter aussehen wird. Er sollte alle 
Oberschwingungen und Netzbrummen bestmöglich unterdrücken, habe an einen 
Bandpass gedacht, das Signal mit einstellbarem Vpp verstärken und 
eventuell einen einstellbaren DC-Offset draufgeben. Zudem sollte das 
Signal recht belastbar sein.
Auch denbkar wäre, über Komparator bzw Integrator eine Rechteck- bzw 
Dreieckfunktion hinzuzufügen.

Da werde ich mich mithilfe des Forums hier aber sicherlich noch 
einarbeiten können.

: Bearbeitet durch User
von Uwe S. (de0508)


Lesenswert?

OK, nun verstehe ich dein Ziel besser.

Vielleicht bringen Dich dieses Buch zum FA-NWT weiter:
# http://www.box73.de/product_info.php?products_id=2402

Das ist ein skalarer Netzwerktester.

Und zur allg. Messtechnik HF-Messungen für den Funkamateur.
Teil 1 - Teil 3 Hans Nussbaum.

Oder die Neuauflage in einem Band:
# http://darcverlag.de/HF-Messungen-fuer-den-Funkamateur

von M. S. (elpaco)


Lesenswert?

Danke für die Empfehlungen!

Ob ich ein ganzes Buch dazu kaufen werde, weiß ich noch nicht. Da ist 
man als Student doch ein wenig im Budget eingeschränkt (den DDS-Chip 
gab's glücklicherweise kostenlos). Habe aber auch noch diverse 
Vorlesungsskripte zur Elektrotechnik, mit deren Hilfe ich mich in die 
Materie einarbeiten kann.

Wenn ich die Ausgangsschaltung entworfen habe, würde ich sie hier auch 
zur Diskussion stellen, um Fehler zu vermeiden.

: Bearbeitet durch User
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.