PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Eine Variable in einem Bereich in ein Byte schreiben/lesen



Kaiser-F
21.06.2006, 15:43
Hallo...

Die Frage ist wahrscheinlich oberpeinlich... aber hilft ja nicht... ich komm einfach nicht drauf! ](*,)

Ich habe ein Satusbyte (status). Dieses hat noch drei freie Bits (0...2).

In diese möchte ich eine Zahl schreiben oder eine Zahl herauslesen.


Ich hab quasi eine Variable x, welche die Werte zwischen 0 und 7 annimmt.
Diese soll mit einem möglichst einfachen Befehl in die unteren drei Bits von Status geschrieben/gelesen werden.


Ich hoffe auf was direktes.. Und nicht die Methode, die statusvariablenbits in alle Himmelsruchtungen zu verschieben....

Ich hoffe ihr versteht was ich meine und könnt mir helfen.

Danke!

Felix G
21.06.2006, 15:53
Also ich würde da einfach erstmal die 3 Bits in Status löschen, und dann per Oder die 3 Bit von x reinkopieren....

also so:

Status &= ~0x07;
Status |= (x & 0x07)

sollte eigentlich klappen...
aber alle Angaben sind wie immer ohne Kanone ;)

SprinterSB
21.06.2006, 15:53
Naja, entweder dir bleiben die Himmelsrichtungen, oder du legst das Ding als bitfield an.

Oder eben händisch:

status = (status & ~0x7) | (wert & 0x7);

Mit Bitfeldern sieht's natürlich viel feiner aus:


typedef struct
{
unsigned feld_foo:3;
...
} status_t;

status_t status;

...
status.feld_foo = wert;

if (status.feld_foo == 5) ...

Kaiser-F
21.06.2006, 16:07
hm, das Händische gefällt mir besser....

Da status ein array ist und für mehrere Parts ein statusbyte ist...

Also status[0] für Part 0 usw....


Kannst mir das veilleicht noch ein bisschen erläutern...
Da komm ich nicht so ganz damit zurecht...

SprinterSB
21.06.2006, 16:13
Äh... status ist ein Array?

uint8_t status[100];

und du willst die Elemente 0..2 setzen?

Eben war status noch ein Byte.

Felix G
21.06.2006, 16:22
Naja...

status & ~0x07 entspricht status aber eben ohne die untersten 3 Bit (die sind 0)

x & 0x07 entspricht den untersten 3 Bit von x (nur um ganz sicher zu gehen, daß man sich nix in status kaputtmacht wenn x doch mal größer ist als 7)

die beiden werte kann man jetzt gefahrlos zusammensetzen (per Oder), und wieder in status schreiben.
(ob man das jetzt in einer oder zwei Zeilen macht ist relativ wurscht)


edit:
@Sprinter
ich glaube er will bei jedem Element jeweils die unteren 3 Bit verändern

Kaiser-F
22.06.2006, 07:13
Ok, ich danke euch beiden! Habt mir sehr geholfen.


Das Statusbyte wird Folgendermaßen verwendet:

Ich programmiere gerade ein Protokoll. Dieses Managed UART0...1 SPI, Parallel usw. mit nur einer eingebindeten Datei.

Die zu sendenden und empfangenen Daten werden in Puffer gespeichert:

BUFFER[anzahl][12];

Bei jedem Puffer wird das erste Byte ( BUFFER[irgendeiner][0] ) für
den status des Puffers verwendet. Die unteren 3 Bits sind eben für die
Schnittstelle, an der gesendet weren soll, oder empfangen wurde.

Sorry an SprinterSB, hätte ich früher sagen sollen...

SprinterSB
22.06.2006, 09:38
Dann ist es am klarsten etwa so

typedef struct
{
unsigned int schnittstelle:3;
unsigned int flag_1:1;
unsigned int status:4;

unsigned char count;
unsigned char buf[12];
} buffer_t;

buffer_t buffers[ANZAHL];


Dann hat jeder Puffer ein Status-Feld (4 Bit), ein Feld zum coden der Schnittstelle (3 Bit), ein Flag (1 Bit) und den eigentlichen Daten-Puffer (12 Bytes) und ein Byte für die Anzahl Bytes im Puffer (count).

Dann kannst du einfach setzen


buffers[2].schnittstelle = SID_UART0;

oder so. Wieso musst du die Schnittstelle überhaupt merken, die kannst du doch fest einem Puffer zuordnen (bzw. ein Puffer für jede Schnittstelle), etwa so:

buffers[SID_UART0].flag = 1;
".schnittstelle" ist damit redundant und kann entfallen. Du arbeitest doch nichst etwa mit malloc???

trickTronic
22.06.2006, 09:51
Hi,
also mit den Bitfeldern würde ich aufpassen.
Die sind lt. ANSI C nicht genormt und können auf unterschiedlichen CPU-Arten (Little/Big-Endian wie PPC und ARM und Pentium) abhängig von deren Compiler Probleme verursachen!
Auf der einen Plattform passt alles, auf der anderen sind alle Bits spiegelverkehrt...
LG, Alex

Kaiser-F
22.06.2006, 10:00
Hi, Danke für die Antworten...

Das mit dem Struct ist ne gute Idee.
Und NEIN, mit malloc oder so sachen mach ich GARNICHTS!
Auch nicht printf oder so a Gschmarre...:-)

Man kann definieren wieviele Puffer man zur verfügung stellt.
Um Speicher zu sparen, können die Puffer je nach gebrauch für
Empfangspuffer/Sendepuffer und für die jeweilige Schnittstelle
Reserviert werden. Funktioniert perfekt! ich werd das Teil bald
Online stellen!

Hab halt jetzt nur für zwei schnittstellen Programmiert....
( ein Bit 0 oder 1 )


Auf jeden Fall.... In diesem Statusbyte sind eben alle Infos was der Puffer gerade macht.

// -=> BUFFER-INFO-DEFINES <=-
#define SMART_B_DEV 0
#define SMART_B_FILL 3
#define SMART_B_RTS 4
#define SMART_B_SEND 5
#define SMART_B_REC 6
#define SMART_B_RTR 7


FILL... Puffer wird gerade mit Informationen Gefüllt und zum Senden vorbereitet.
RTS...Ready to Send
SEND... Wird gesendet
REC....Receiving
RTR....Ready to read

und die ersten Bits sind eben für die schnittstellt gedacht.


Wenn was unternommenwerden soll, wird erst nach einem Freien Puffer gesucht. Ein puffer ist dann frei, wenn das Infobyte 0 ist.

Deshalb möchte ich auf das Struct lieber verzichten...
Wenns ist mach ich halt ne Funktion die mir den Divice auslest oder reinschreibt....





sollte eigentlich klappen...
aber alle Angaben sind wie immer ohne Kanone ;)
--> lol :-)

Kaiser-F
22.06.2006, 10:10
Zur Not muss ichs dann so machen:


void WRITE( uint8_t n, uint8_t device ){
if( device > 7 ){ device = 7; }
BUFFER[n][0] &=~ (1<<2)|(1<<1)|(1<<0);
BUFFER[n][0] = BUFFER[n][0] + device;
}

uint8_t READ( uint8_t n ){
device = (BUFFER[n][0]<<5);
device = (device>>5);
return device;
}

Aber es geht mir eigentlich nur darum, diese zwei Dinge zu vereinfachen.

SprinterSB
22.06.2006, 10:22
Hi,
also mit den Bitfeldern würde ich aufpassen.
Die sind lt. ANSI C nicht genormt und können auf unterschiedlichen CPU-Arten (Little/Big-Endian wie PPC und ARM und Pentium) abhängig von deren Compiler Probleme verursachen!
Auf der einen Plattform passt alles, auf der anderen sind alle Bits spiegelverkehrt...
LG, Alex
Das ist hier egal weil die Bitfields hier nicht transferiert werden. Ob Bits/Bytes little oder big endian sind spezifiziert C auch nicht, das Problem hast du ohnehin immer. Der Inhalt eines Bitfields zu übertragen ist also genauso sicher/unsicher wie einen char zu übertragen.

Das von dir angerissene Problem kann dann auftreten, wenn man die ganze Struktur en block überträgt.

Das Endian-Problem kannst du leicht lösen, indem du es zur Laufzeit abfragst.

Kaiser-F
22.06.2006, 10:25
Achja... ich hätte ja das Händische fast vergessen...

So müsste es ja funktionieren....


void WRITE( uint8_t buffer, uint8_t device ){
BUFFER[buffer][0] = (BUFFER[buffer][0] & 0xF8) | (device & 0x07);
}


uint8_t READ( uint8_t buffer ){
device |= (BUFFER[buffer][0] & 0x07);
}


EDIT: Gibds eigendlich ne Seite wo man so sachen nachschlagen kann? in meinem C-Buch hab ich sowas nochnie gesehen...
Und in den Tutorials ist das auch immer nicht so ganz drinn...

SprinterSB
22.06.2006, 10:28
[...] Wenn was unternommenwerden soll, wird erst nach einem Freien Puffer gesucht. Ein puffer ist dann frei, wenn das Infobyte 0 ist.

Deshalb möchte ich auf das Struct lieber verzichten...

Womit kollidiert denn struct? Wenn es so ist, hast du nen Designfehler.


If (buffers[i].Infobyte == 0) ...

Es kommt auch darauf an, was an Speicher du sparen willst. Wenn du Flash sparen willst sieht die Antwort anders aus, als wenn du RAM sparen möchtest. Eine handvoll Bits zu sparen bedeutet idR einem anderen Code der empfindlich mehr Flash schluckt.

Kaiser-F
22.06.2006, 10:36
Womit kollidiert denn struct? Wenn es so ist, hast du nen Designfehler.

If (buffers[i].Infobyte == 0) ...


Ich glaube da reden wir aneinander vorbei... ich will bloß die uint8_t in die unteren drei Bits schreiben und herauslesen...
Wird ein puffer nicht mehr gebraucht, dann wird dieses infobyte auf 0 gesetzt. Er steht dann wieder frei zur verfügung.



Es kommt auch darauf an, was an Speicher du sparen willst. Wenn du Flash sparen willst sieht die Antwort anders aus, als wenn du RAM sparen möchtest. Eine handvoll Bits zu sparen bedeutet idR einem anderen Code der empfindlich mehr Flash schluckt.

Ich möchte RAM sparen. Und zwar wird das dadurch realisiert, dass
zB 8 Puffer zur verfügung stehen. Alle schnittstellen können diesen
also sende- sowie als empfangspuffer verwenden.

Und nicht extra puffer für jede schnittstelle....
Damit werden die Puffer Optimal genutzt.

SprinterSB
22.06.2006, 10:47
Mach Infobyte als Bitfeld der Länge 3, that's it. Jedenfalls wird der Code dadurch lesbarer und kann ganz einfach, auf eine Flash-sparene Variante umgestellt werden :-)


Auch egel, du hast ja jetzt Infos genug...

Kaiser-F
22.06.2006, 10:53
Jap, Infos hab ich jetzt wirklich genug :-).

Die Idee mit dem Bitfeld ist ech super!
( Ich hab überhaupt schon gemerkt, dass du Bitfelder liebst :-) )

Sei mir nicht böse, aber ich nimm deinen aller ersten Vorschlag :-):


Naja, entweder dir bleiben die Himmelsrichtungen, oder du legst das Ding als bitfield an.

Oder eben händisch:

status = (status & ~0x7) | (wert & 0x7);


Hab ich gerade getestet... ist Platzsparend und haut super hin!


Mir ist es in diesen Fall lieber, wenn das Puffer-Array ein stinknormales Array bleibt. Aber für meine Tasteranwendungen nimm ich brav Bitfelder her :-).

Danke für deine Hilfe.

SprinterSB
22.06.2006, 11:01
Ich hab überhaupt schon gemerkt, dass du Bitfelder liebst :-)

Nö, nicht wirklich. Ich denke nur, die sind einfacher zu benutzen und die Quelle bleibt besser lesbar, was für Einsteiger wohl angenehmer ist.

Ich selbst verwende keine Bitfelder, weil der Code damit wie gesagt länger (und damit auch langsamer) wird.

Kaiser-F
22.06.2006, 11:06
da hast du recht...

Was auch immer recht schwierig zu finden ist, sind genau so sachen:

status = (status & ~0x7) | (wert & 0x7);
oder if( status & (1<<RTR) ){}

Gibs da nicht ne seite wo sowas steht... oder sind dass dan eh alle möglichkeiten...

Weisst schon... so §$%&/( sachen hlt :-)....?

SprinterSB
22.06.2006, 12:39
Das ist ja immer das gleiche Schema

Bit löschen: AND (0=bit wird 0, 1=bit bleibt unverändert)
Bit setzen: OR (1=bit wird 1, 0=bit bleibt unverändert)
Bit wechseln: XOR (1=bit wird gewechselt (1<->0), 0=bit bleibt unverändert)
Alle Bits wechseln: NOT

Und dann eben noch Bits links oder rechts schieben. Das sind die 5 Grundoperationen (XOR wird nur selten gebraucht) für Bitmanipulationen.