Hi, Ich weis nicht ich finde einfach keine Lösung um aus einer Variable die Bits auszulesen. Vlt stelle i mich auch einfach dumm an. Hier mal ein Beispiel: int main(void){ int array[3] = {0x07, 0xEF, 0xA3} //jetzt möchte ich Beispielsweise aus array[2] die Bits auslesen } Wie funktioniert das? Muss i irgend etwas anders machen? Vielen Dank schon mal im Vorraus.
also bei array[2] is das ja 0xEF also binär 0b1110 1111 und so möchte ich eben mit den einzelnen bits arbeiten also ich möchte prinzipiel nur den binären wert der Variable auslesen
:
Bearbeitet durch User
Bitte klären: wieviele Bits hat das int? Dann durch bitweisen Test (Vergleichsoperationen die einzelnen Bits bestimmen), möglicherweise bringt auch printf etwas.
F. H. schrieb: > also binär 0b1110 1111 Das ist keine Standard-Notation in C, deshalb lieber mit Vorsicht genießen.
F. H. schrieb: > also ich möchte prinzipiel nur den binären wert der Variable auslesen auslesen ist schlecht ausgedrückt. Aber was du tun kannst: Du kannst natürlich feststellen, ob ein Bit auf 1 oder auf 0 ist. Und je nachdem machst du dann etwas anderes. Das funktioniert genau gleich, wie wenn man von einem Portpin feststellt ob er auf 1 oder auf 0 ist. Sozusagen ein universeller Mechanismus. Also. Nicht 'auslesen'. Sondern: feststellen ob 1 oder 0 und dann darauf reagieren.
F. H. schrieb: > also ich möchte prinzipiel nur den binären wert der Variable auslesen Es gibt keinen "binären" oder "hexadezimalen" Wert. Es gibt nur einen Wert. Was willst du wirklich? Die Binärdarstellung als String, also als Zeichenkette? Ein einzelnes Bit extrahieren? Etwas anderes?
Okay Vielen Dank also sollte das theoretisch so funktionieren...oder? int main(void){ int array[3] = {0x07, 0xEF, 0xA3} int iPIN1 = array[2] & (1<<0) //müsste ja dann eine 1 sein int iPIN5 = array[2] & (1<<4) //müsste ja dann eine 0 sein }
:
Bearbeitet durch User
F. H. schrieb: > int iPIN1 = array[2] & (1<<0) //müsste ja dann eine 1 sein Ja, aber nur zufällig. > int iPIN5 = array[2] & (1<<4) //müsste ja dann eine 0 sein Ja. aber auch nur zufällig. Wenn im Ausgangswert ein 1 Bit gewesen wäre, dann wäre iPIN5 hier nicht 1, sondern 32 (nämlich 1<<4) Für iPIN1 stimmt das ganze zwar. Aber auch nur deswegen, weil es sich hier um das Bit 0 handelt, und die Wertigkeit dieses Bits ja nachdem 0 oder 1 ist. Für die restlichen 7 Bits ist das zu kurz gedacht. Die Grundidee ist allerdings korrekt. Wenn auch, je nachdem wie es dann weiter geht, unter Umständen nur die halbe Miete.
:
Bearbeitet durch User
F. H. schrieb: > okay und wie mach i das dann am besten? Such dir eine Variante aus:
1 | int iPIN5 = (_Bool)(array[2] & (1<<4)); |
2 | int iPIN5 = (array[2] & (1<<4)) ? 1 : 0; |
3 | int iPIN5 = ((array[2] & (1<<4)) != 0); |
4 | int iPIN5 = !!(array[2] & (1<<4)); |
F. H. schrieb: > okay und wie mach i das dann am besten? Neben dem, was Stefan angeführt hat: Am besten - gar nicht. Wozu auch? Wozu benötigst du die einzelnen Bits? Das stellt man zuerst fest und danach entscheidet man, wie man dann an der verwendenden Stelle auf die Einzelbits zugreift. Je nachdem greift man nämlich nicht mehr so auf die einzelnen Bits jeder Stelle zu, sondern benutzt eine etwas andere, abgewandelte Technik. Im Grunde ist das zwar immer noch ein Maskieren und Verunden, aber man kann da einiges einsparen, wenn einen nicht interessiert ob da jetzt 0 oder 1 rauskommt, sondern 0 oder n auch schon reicht.
:
Bearbeitet durch User
Weil ich eine Matrix ansteuer und immer einer variable vorgibt welche leds leuchten müssen. Und eine Variable definiert eine reihe der Matrix. Ich kann das so aber nicht direkt ausgeben, da i die matrix auf schiebe registern habe und somit i die signale einzeln durchschiebe.
F. H. schrieb: > Weil ich eine Matrix ansteuer und immer einer variable vorgibt welche > leds leuchten müssen. Ah siehst du. Dazu brauchst du den Wert eines Bits nicht in einer Variablen (und schon gar nicht in einer int Variablen! int willst du nicht benutzen, wenn es nicht sein muss. Wenn du mit 8 Bit durchkommst, dann nimmst du uint8_t oder int8_t und nicht das 16-Bit 'int')
1 | for( uint8_t i = 0; i < 8; i++ ) |
2 | {
|
3 | if( wert & 0x01 ) |
4 | Bit ist 1, mach was |
5 | else
|
6 | Bit ist 0, mach was |
7 | |
8 | wert >>= 1; |
9 | }
|
denn was du auf keinen Fall möchtest, ist ein
1 | .... & ( 1 << i ) |
in irrgend einer Form. Denn das ist ein teure Operation. Da schiebst du lieber einen Wert sukzessive um jeweils 1 Stelle nach rechts und testest immer auf das 0-te Bit (oder schieben nach links und testen auf das 7-te Bit, wenn die Reihenfolge anders rum sein soll)
Kann i das dann auch direkt so machen?
1 | for( uint8_t i = 0; i < 8; i++ ) |
2 | {
|
3 | if( wert & i ) |
4 | Bit ist 1, mach was |
5 | else
|
6 | Bit ist 0, mach was |
7 | |
8 | wert >>= 1; |
9 | }
|
F. H. schrieb: > Kann i das dann auch direkt so machen? Das weiß ich nicht, ob du die Programmteile, die ich jetzt hier nicht ausgeführt habe, wie zb die Ansteuerung der Schieberegister, alleine hinkriegst. Aber die Abarbeitung der einzelnen Bits in einem Byte, welches in 'wert' steht, die kannst du so machen - drum hab ich das ja aufskizziert, wie man das in so einer konkreten Situation macht.
F. H. schrieb: > Kann i das dann auch direkt so machen? machen ja, aber etwas sinnvolles kommt dabei nicht raus.
Ja danke Nein das mit den Schieberegistern habe Ich schon. Ich bin nur noch nicht ganz so vertraut mit C.
F. H. schrieb: > Kann i das dann auch direkt so machen? ach jetzt seh ichs erst > if( wert & i ) Nein. Völlig falsch. Wozu soll das gut sein? Du scheinst nicht begriffen zu haben, was das Konzept ist. Anstatt sich jeweils ein eigenes 'Fenster' zu machen, mit dem man einen Blick auf das i-te Bit erhascht, dreht man den Spiess um. Man macht 1 immer gleiches Fenster und schiebt die Bits unter dem "Fenster" durch. Das ist nämlich für den µC einfacher, weil die Erzeugung des "Fensters" für einen AVR eine aufwändige Sache ist. Im Endeffekt kommt aber beides aufs gleiche raus.
:
Bearbeitet durch User
Ist der Speicher so knapp? ich würde lieber 1 Byte für einen Matrixpunkt nehmen. Das Bit hin und hergeschiebe ist zwar interessant, und manchmal sinnvoll. Aber jeden Matrixpunkt mit einem Namen ansprechen zu können, ist für mich die einfachere Lösung. Dann bracht man nicht jedesmal so tolle Bitmanipulationen.
Achso Jetzt hab ich es verstanden. deswegen auch das "wert >>= 1;" Vielen Dank, jetzt machts Sinn.
Sry bin in dieser Materie noch nicht ganz so durchgestiegen. Deswegen frag ich ja auch nach.
F. H. schrieb: > Sry bin in dieser Materie noch nicht ganz so durchgestiegen. > Deswegen frag ich ja auch nach. Das Problem ist eigentlich, dass das hier noch der einfachste Teil der Ansteuerung einer Matrix ist. Eine LED-Matrix ist nun mal kein Einsteigerprojekt, auch wenn es viele immer wieder dafür halten (und mir rätselhaft ist, was an einer kleinen LED-Matrix so toll sein soll - aber das muss jeder für sich entscheiden)
:
Bearbeitet durch User
Damit es Dir später nicht noch auf die Füße fällt: F. H. schrieb: > also bei array[2] is das ja 0xEF Nein. Gemäß Deines Eröffnungsbeitrags ist der Wert von array[2] gleich 0xA3.
Hab des jetzt mal versucht so umzusetzten mit der Bitmanipulation. Allerdings kommt immer 0 raus
1 | uint8_t iValue = 0b00000001 |
2 | |
3 | for(uint8_t i = 0; i < 8; i++){ |
4 | if(wert & 0x01) |
5 | //Trifft niemals ein
|
6 | else
|
7 | |
8 | iValue >>= 1; |
9 | }
|
F. H. schrieb: > Allerdings kommt immer 0 raus Woher weist Du das? > if(wert & 0x01) Wo kommt denn plötzlich die Variable "wert" her? Du musst wohl etwas mehr Code zeigen.
Sry so funktioniert es schon. Nur sobald der Wert über einem bit ist klappt es nicht mehr
:
Bearbeitet durch User
Möglicherweise währe es einfacher, wenn du die SPI Hardware benutzt für das Schieberegister. Dann kannst du nämlich deine ganze 8-Bit Variable mit dpi_fast_shift(deine_variable); übergeben. Aus deinem Code werde ich leider überhaupt nicht schlau, aber hier die simpelste Variante (nicht optimiert) wie ich es machen würde:
1 | if (variable & 1) |
2 | {
|
3 | //mach was
|
4 | }
|
5 | else
|
6 | {
|
7 | //mach was anderes
|
8 | }
|
9 | if (variable & 2) |
10 | {
|
11 | //mach was
|
12 | }
|
13 | else
|
14 | {
|
15 | //mach was anderes
|
16 | }
|
17 | if (variable & 4) |
18 | {
|
19 | //mach was
|
20 | }
|
21 | else
|
22 | {
|
23 | //mach was anderes
|
24 | }
|
und so weiter
:
Bearbeitet durch User
Mit Klammern {}? char iValue[8] = { 1, 0, 0, 0, 0, 0, 0, 1 }; for (int i = 0; i < 8; i++){ if (iValue[i] == 0) { iValue[0] <<= 1; ; } else { iValue[0] <<= 1; ; } }
F. H. schrieb: > Sry so funktioniert es schon. > Nur sobald der Wert über einem bit ist > klappt es nicht mehr Dann zeig halt mal den RICHTIGEN Code. Dann hilft dir auch jemand, all die kleinen blöden Fehler zu eliminieren, die du eingebaut hast.
:
Bearbeitet durch User
Sean Goff schrieb: > Aus deinem Code werde ich leider überhaupt nicht schlau, aber hier die > simpelste Variante (nicht optimiert) wie ich es machen würde: Das ist doch Quatsch Wenn du mit einer Schleife nicht umgehen kannst, dann lass es und red nicht Anfängern so einen Unsinn ein. SPI Hardware einzusetzen ist grundsätzlich ok. Aber auch die 'händische' Ausgabe zu Fuss ist keine Raketentechnik und eine derartige Funktion ist in weniger als 14 Zeilen Code abgehandelt
1 | void outputByte( uint8_t wert ) |
2 | {
|
3 | for( uint8_t i = 0; i < 8; i++ ) |
4 | {
|
5 | if( wert & 0x01 ) |
6 | ein 1 Bit auf die Datenleitung schalten |
7 | else
|
8 | ein 0 Bit auf die Datenleitung schalten |
9 | |
10 | Clock auf 1 |
11 | Clock auf 0 |
12 | |
13 | wert >>= 1; |
14 | }
|
15 | }
|
(die Portoperationen müssen noch ausformuliert werden) Bei einer Schieberegisterkette bestehend aus 595 Schieberegistern wird dann hinten nach, nachdem alle Bytes ausgegeben worden sind und somit die Schieberegister neu befüllt wurden, noch der Puls auf RCLK ausgegeben, damit die Schieberegister den neuen Inhalt auch auf die Ausgänge durchschalten.
1 | void outputBytes( uint8_t byte1, uint8_t byte2, uint8_t byte3 ) |
2 | {
|
3 | outputByte( byte1 ); |
4 | outputByte( byte2 ); |
5 | outputByte( byte3 ); |
6 | |
7 | RCLK auf 1 |
8 | RCLK auf 0 |
9 | }
|
SPI Hardware dafür lass ich mir gerne einreden. Aber eigentlich ist die ganze Sache so simpel, dass die jeder in 10 Minuten programmieren können muss. Und zwar auch dann, wenn ich ihn morgens um 4 aus dem Bett hole.
:
Bearbeitet durch User
Vielen dank aber die ausgabe habe ich schon längst. Ich versuche nur noch schrift und "animationen" einzufügen. Aber Trotzdem vielen Dank
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.