mikrocontroller.net

Forum: Compiler & IDEs serielle Daten über einen Pin einlesen


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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. ;-)

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Damit speicherst Du jedes Bit in einem Byte, das wären dann 7 Bit
verschwendung pro Empfangenem Bit!

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ 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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jaja, hast Recht, noch ein Bug, der in Peters Code gefixt war. ;-)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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. :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.