Forum: Compiler & IDEs Serielle Daten bitweise in die Variable schreiben


von Sam (Gast)


Lesenswert?

Hallo Leute,

ich versuche über eine serielle Schnittstelle, 10 Bits zu empfangenn, 
und diese in einer Variablen zu speichern. Das Ganze versuche ich halt 
"zu Fuß" zu realisieren.

Um mich direkt ein bisschen zu outen, ich bin mit Arduino 
"aufgewachsen", versuche jetzt aber nach und nach in der üblichen C 
Programmiersprache (ohne Arduino Libs) zu programmieren. Eben aus den 
Gründen, um den Code besser verstehen zu können, flexibler zu bleiben, 
um in Zukunft nicht nur an handvoll Atmel µC gebunden zu sein.

Den ersten Test habe ich so ausgeführt.
1
digitalWriteFast(CLK, LOW);    
2
digitalWriteFast(CLK, HIGH);
3
value |= digitalRead(DATAPIN) << 9;
4
5
...
6
...
7
...
8
9
digitalWrite(CLK, LOW);    
10
digitalWrite(CLK, HIGH);
11
value |= digitalRead(DATAPIN) << 0;

Zuerst wird einmal Clock-Cycle durchgeführt und dann der Pegel 
eingelesen und dann an der entsprechenden Bit-Stelle, in einem Integer 
abgelegt.

Es hat auch wunderbar in einer for-Schleife funktioniert.

Nun würde ich gern etwas schneller lesen, weil digitalRead/Write zum 
Einschlafen sind und da komme ich irgendwie nicht weiter.

Ich ich habe anstelle von digitalRead schon vieles mit Bitmanipulation 
ausprobiert und komme aber zu keinem brauchbaren Ergebnis. Wenn ich mir 
die Variable dann im seriellen Monitor ausgeben lasse, habe ich dort 
meistens mehr als 10 Bits.

Zwischendurch dachte ich, dass ich den µC irgendwie gehimmelt habe. Aber 
mit "digitalRead" klappt es nach wie vor, nur eben zu langsam.


Bin für jede Hilfestellung sehr dankbar :-)

von Sam (Gast)


Lesenswert?

Achsoo, der Code stimmt so nicht ganz.

Ich habe das mal als Test mit digitalWriteFast ausprobiert, jedoch 
meckert der Compiler, bei dieser Bibliothek.
1
digitalWrite(CLK, LOW);    
2
digitalWrite(CLK, HIGH);
3
value |= digitalRead(DATAPIN) << 9;
4
5
...
6
...
7
...
8
9
digitalWrite(CLK, LOW);    
10
digitalWrite(CLK, HIGH);
11
value |= digitalRead(DATAPIN) << 0;

von Peter D. (peda)


Lesenswert?

Hier ein Beispielcode zum Einlesen 2 * 74HC165 kaskadiert:
1
#include <avr\io.h>
2
3
struct bits {
4
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
5
} __attribute__((__packed__));
6
7
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
8
9
#define SPI_CLK         SBIT( PORTB, 0 )        // clock
10
#define SPI_CLK_oe      SBIT( DDRB,  0 )
11
#define SPI_MISO_in     SBIT( PINB,  2 )        // input
12
#define HC165_LD        SBIT( PORTB, 3 )        // parallel load
13
#define HC165_LD_oe     SBIT( DDRB,  3 )
14
15
uint16_t read_2xhc165( void )
16
{
17
  uint8_t i;
18
  uint16_t b = 0;
19
20
  SPI_CLK_oe = 1;
21
  HC165_LD_oe = 1;
22
  HC165_LD = 0;
23
  HC165_LD = 1;
24
25
  for( i = 16; i; i-- ){
26
    b <<= 1;
27
    if( SPI_MISO_in )
28
      b |=1;
29
    SPI_CLK = 0;
30
    SPI_CLK = 1;
31
  }
32
  return b;
33
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> #include <avr\io.h>

Peter, auch unter Windows funktioniert der Slash in Include-Pfaden 
tadellos.

#include <avr/io.h>

ist daher portabler.

von Jürgen S. (jurs)


Lesenswert?

Sam schrieb:
> Zwischendurch dachte ich, dass ich den µC irgendwie gehimmelt habe. Aber
> mit "digitalRead" klappt es nach wie vor, nur eben zu langsam.


Wenn Du, wie man an Deinem Beispielcode sehen kann, ein Makro für 
"digitalWriteFast" installiert hast, dürftest Du ziemlich sicher auch 
ein Makro für "digitalReadFast" installiert haben.

Wenn es mit "digitalRead" funktioniert, wäre die erste Maßnahme also, 
für eine Konstante als Datenpin das Makro "digitalReadFast" zu 
verwenden. Das beschleunigt die Dinge schon mal etwas.

Funktioniert es dann?

Wenn das immer noch nicht schnell genug ist, gehst Du mit direkter 
Registerprogrammierung dran.

Und wenn nicht die Geschwindigkeit, sondern Deine Programmlogik das 
Problem ist, dann prüfe mal, ob Du in Deinem nicht gezeigten Code die 
Variable "value" überhaupt auf Null setzt, bevor Du sie mit den 
gelesenen Werten veroderst.
1
 value = 0;
2
...
3
  value |= 
4
...
5
  value |= 
6
...
7
  value |=

Wenn Du die Variable nicht anfangs auf null setzt und stattdessen einen 
Zufallswert aus dem RAM abgreifst, hat sie hinterher ziemlich sicher 
mehr Bits gesetzt als Du sie mit den Veroderungen setzt.

von Sam (Gast)


Lesenswert?

Vielen Dank für eure Antworten.

Ich glaube, ich sollte mich noch etwas tiefer in die ganzen Anweisung 
(Operanden? <<= ) einarbeiten.

@Jürgen S. ja, die digitalWriteFast Bibliothek habe ich ausprobiert.
Leider hatte ich immer eine Fehlermeldung "invalid type argument of 
'unary *'".
Ich habe mir die Bibliothek etwas genauer angeschaut und noch ein Befehl 
digitalWriteFast2 gefunden. Damit habe ich keine Fehlermeldungen und ich 
bekomme auch meine 10Bits. Was da aber genau gemacht wird, muss ich mir 
noch genauer anschauen.

Im Moment hüpfe ich noch durch die Tutorials durch.


Nochmal 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
Noch kein Account? Hier anmelden.