Halli hallo nochmal an Alle! Und zwar bin ich auf folgendes Problem gestoßen. Ich bekomme an einem Eingang (PORTC, PIN=0) serielle Daten. Diese möchte ich nun bitweise einlesen und abspeichern. Meine Idee sieht so aus: for (BitCounter=0;BitCounter<80;BitCounter++) { Speicher[ChipIdBitCounter] = inp(PINC); } Speicher[]ist ein int array....nur so wird ja immer der ganze Port gelesen und abgespeichert oder? Welche Lösung nimmt man überlicherweise für so ein Problem. Hab schon diese Funktion gefunden, for (j=0;j<=7;j++) //Schleife zum einlesen der 8 Bits { daten<<=1; // Variable einmal schieben if ( bit_is_set(PIND,2) // Prüfen ob Bit = 1 { daten++;} //wenn Bit = 1 dann Daten + 1. LSB wird dann 1 } aber ich versteh ich nicht so recht und denke auch nicht das es bei mir so funktioniert. Wer hat Vorschläge und Lösungen. Wäre Euch sehr dankbar. Ciao Thomas
Bitoperatoren in C Bitoperatoren in C Bitoperatoren in C Lies und verstehe alles, was zu & | ^ << >> ~ in einem guten C-Buch geschrieben steht. for (ByteCounter = 0, mask = 1; ByteCounter < 80 / 8;) { if ((PINC & (1 << yourbitnumber)) != 0) Speicher[ByteCounter] |= mask; if (mask == 0x80) { mask = 1; ByteCounter++; } else { mask <<= 1; } } Verstehen mußt Du es aber bitte selbst. ;-)
Achso: Nachdem Du verstanden hast, wie die Bitoperatoren in C funktionieren ;-) kannst Du noch überlegen, ob nicht die hardware-SPI was für Dich wäre.
@Jörg, das ist aber nicht das selbe. Wenn Du mit einer Maske arbeitest, mußt Du sie in die andere Richtung schieben: unsigned char daten = 0; unsigned char mask = 0x80: do{ if ((PINC & (1 << yourbitnumber)) != 0) daten |= mask; }while( mask >>= 1 ); @Thomas, in allen Beispielen fehlt aber noch der Teil zur Synchronisation, entweder mit einem 2. Clockpin oder per Timerintervall. Peter
> Wenn Du mit einer Maske arbeitest, mußt Du sie in die andere > Richtung schieben: Nicht zwingend, das hängt ja davon ab, in welcher Folge die Bits im Byte gespeichert werden sollen. Darüber hat sich Thomas schlicht nicht ausgelassen. In meinem Fall wird das erste eingelaufene Bit im LSB gespeichert (das wäre ``true little-endian'' ;-), in Deiner Variante im MSB.
Hallo Jörg/Peter, danke für die Antworten. Werde es mir morgen mal in Ruhe anschauen. Vorallem die Bitoperatoren ;-))) ich würde die Bits einfach so abspeichern wie sie kommen. Also 1.Bit ist dann wohl auch MSB. Eigentlich auch erstmal egal ;-)))...Hauptsache ich komm an die Daten. schönen Abend noch Ciao Thomas
Guten Morgen Freunde, also ich habe mich mal mit den Bitoperatoren beschäftigt und versucht Euren Code zu verstehen. Aber so ganz bin ich noch nicht dahinter gekommen. (ByteCounter = 0, mask = 1; ByteCounter < 80 / 8;) Wieso teilst Du da hinten nochmal durch 8??? if ((PINC & (1 << yourbitnumber)) != 0) Diese Zeile verstehe ich soweit erstmal ganz gut. yourbitnumber in Verbindung mit Pinc und dem 1 << ergibt das Pin, wo ich lesen will. != bedeutet soviel wie ungleich Null wenn ich mich nicht irre. Speicher[ByteCounter] |= mask; dann wird ne 1 in den Speicher an der Stelle von ByteCounter geschrieben if (mask == 0x80) { Und das ist mir jetzt zu hoch. Also 80hex sind 1000 0000. mask ist 1. Wie soll das also == sein?? mask <<= 1; << bedeutet linksschieben aber in Verbindung mit =???? Was macht das genau?? Sorry, wenns nervt....aber bin nicht so der C-Guru ;-)) Ciao Thomas
> Wieso teilst Du da hinten nochmal durch 8? Weil es ein *byte*counter sein soll, Du aber (Deinem Ursprungsposting nach) 80 bits hast. Allerdings fehlt in meinem Code die innere Schleife für jeweils 8 Bits, die ist bei Peter dafür da. > if (mask == 0x80) { > Und das ist mir jetzt zu hoch. Also 80hex sind 1000 0000. mask ist > 1. Nicht mehr, wenn diese if-Anweisung erfüllt sein soll. Denn: > mask <<= 1; > << bedeutet linksschieben aber in Verbindung mit =? Nun, ganz normal wie in C üblich: a <foo>= b; ist ein Äquivalent für a = a <foo> b; mask wird also um ein Bit nach links verschoben. Damit sollte Dir auch klar sein, warum sie irgendwann 0x80 werden kann. Wie gesagt, um die Bitschieberei fehlt bei mir noch eine innere Schleife, außerdem mußt Du, wie Peter richtig bemerkte (war mir erst nach meinem Posting aufgefallen) in der inneren Schleife noch irgendwas haben, was an PINC den Empfang des nächsten Bits triggert. Das kann z. B. sowas sein wie: PORTC |= (1 << yourtriggerbit); PORTC &= ~(1 << yourtriggerbit); um einen kurzen Impuls des yourtriggerbit-sten Bits in PORTC auszulösen. Die Schreibweise ist so ganz und gar gängig (bspw. in den Quellen von Betriebssystemtreibern), nur damit Du ein wenig in der Übung mit den Bitoperatoren bleibst. :-) Sofern yourtriggerbit zur Compilezeit konstant ist, würde der AVR-GCC daraus übrigens (bei eingeschalteter Optimierung) SBI und CBI Anweisungen zimmern.
@Jörg also die Schleife habe ich jetzt erstmal verstanden. Nur wieso ist das mit der Maske gut. Geht das nicht einfacher? Sonst muss man doch das Feld vorher mit Nullen intitialisieren? for (ChipIdBitCounter=0;ChipIdBitCounter< 80;ChipIdBitCounter++){ if ((PINC & (1 << 0)) != 0 { Speicher[ChipIdBitCounter] = 1;} else { Speicher[ChipIdbitCounter] = 0;} } Geht diese Schleife oder ist das zu simpel? Das mit den nächsten Bit triggern ist noch so ein Problem, da ich noch nicht weiss wie die Daten ankommen. Die Frage ist doch eher in welcher Zeit der Pin C abgefragt wird. Wenn man das in der gleichen Frequenz kann wie die ankommenden Daten müßte es doch gehen? Ciao Thomas
Damit speicherst Du jedes Bit in einem Byte, das wären dann 7 Bit verschwendung pro Empfangenem Bit!
@ OldBug hm, da ist was dran. aber bei dieser operation:siehe auch weiter oben Speicher[ByteCounter] |= mask; werden doch immer nur "1" gespeichert oder? Ahoi Thomas
Jaja, hast Recht, noch ein Bug, der in Peters Code gefixt war. ;-)
Hallo nochmal in die Runde! ich habe jetzt mal noch einen Vorschlag für die Schleife(ohne Trigger): for(ByteCounter=0;mask=0x80,ByteCounter<10) { do { if ((PINC & (1 << yourbitnumber)) != 0){ Speicher[ByteCounter] |= mask; } mask >>=1; while {mask != 0 ) Bytecounter++; } Was meint Ihr dazu? Theoretisch müßten jetzt genau 10 Bytes also 80 Bits im Speicher liegen. Und zwar 1 Bit ist MSB. Der Trigger müsste dann wohl noch in die do-while Schleife. Ciao Thomas
Die Zuweisung im zweiten Teil der for-Anweisung ist verwirrend. ;-) Außerdem bleibt natürlich das Problem, daß die entsprechende Speicherstelle erstmal auf 0 gesetzt werden muß. Das kannst Du natürlich auch außerhalb der Schleife (z. B. mit einem memset()) tun. Ansonsten: for (ByteCounter = 0; ByteCounter < 10; ByteCounter++) { uint8_t data = 0; uint8_t mask = 0x80; do { ... data |= mask; mask >>= 1; while (mask != 0); Speicher[ByteCounter] = data; } Damit bist Du effektiv bei Peters Vorschlag. :-)
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.