Forum: Mikrocontroller und Digitale Elektronik Serielle Datenübertragung


von Coco J. (Gast)


Lesenswert?

Schönen guten Abend,

ich habe das forum schon nach meinem Betreff durchstöbert, stoße aber 
meißt auf "USB->Seriell" "Seriell->Parallel" und sowas in der art.

Ich möchte:
in C programmieren
2 AVRs über 2 Leitungen verbinden (SData und Sclock)
eine Float zahl (zweierkomplement mit exponent um komma zu setzen) 
übergeben (notfalls auch jedes Zeichen einzelnd als String)

mein Problem

Verschiedene Datentypen auseinandernehmen dass ich die einzelnden bits 
habe
diese zu extrahieren so dass ich bei jedem "step" eine 1 oder eine 0 
habe

analog dazu

auf der anderen seite die 1 und 0 zusammenzusetztn und wieder in den 
String/float zu verwandeln.. (und auch villt gleich wieder von String in 
Int/float,.. falls es nicht so ist wie in java.. da hatten wir ja eine 
lib für.. ^^

also rein mit Flipflops und schieberegistern würde ich das ganze denk 
ich hinbekommen (mit der übertragung) aber ich wollte ja in C bleiben^^

mfg Coco (schonmal vielen dank fürs duchlesen ;))

von Der S. (derschelm)


Lesenswert?

Du willst also an die Bits eines Float herankommen, diese versenden und 
auf der anderen Seite wieder zusammensetzen?

Versuch mal eine Union (Annahme float=4Bytes und damit genau so lang wie 
ein unsigned long)

dann ungefähr:

union  {
  unsigned long wort;
  float gleit; ) LONGFLOAT ;

Das unsigned long und das float belegen DENSELBEN Speicherplatz, so dass 
Du das float reinschreiben kannst und mit Hilfe des unsigned long bequem 
an die einzelnen Bits kommst.

Näheres einfach mal nachgoogeln (sorry, aber ich habe jetzt keine Lust 
mehr, die Details zu erklären, aber das findest Du sicher auch ohne mich 
raus).

Viel Spaß noch

von Juergen R. (stumpjumper)


Lesenswert?

Nur mal ein Schuß ins blaue,
normalerweise werden nicht die einzelnen Bits versendet sondern die 
Daten Byteweise an die serielle Schnittstelle übergeben. Das Bitweise 
versenden wird dann intern über ein Schieberegister abgewickelt das 
macht die Hardware.
Soll das ganze über einen "normalen" Portpin gemacht werden muß man das 
allerdings selber machen. Auch da würde ich erst mal in Bytes wandeln 
und diese dann über Schiebeoperationen links bzw. rechts schieben und 
dann das linke bzw. rechte Bit mit "1" bzw. "128" vergleichen, je 
nachdem welche schiberichtung man bevorzugt.

von Sonstwer (Gast)


Lesenswert?

Such im Forum, bei google, im Datenblatt oder im Tutorial nach "SPI". 
Wenns "gleichberechtigt" bidirektional sein soll kannst du den "UART" 
bzw "USART" benutzen. Da brauchst du nichtmal ne Taktleitung.

von Martin (Gast)


Lesenswert?

oder auch I²C.
Und wenn eine Hardwareschnittstelle verwendet werden soll könnte man die 
union auch so abändern:

union  {
  char speicher[4];
  float gleit; ) MEINEUNION ;

von Blackbird (Gast)


Lesenswert?

Und wenn es ohne Hardwareunterstützung funktionieren soll: es gibt noch 
"Software-UART" und das "124-Protokoll" von Peter Dannegger.

Blackbird

von Coco J. (Gast)


Lesenswert?

ich wollte wie gesagt das I2C bzw TWI (ist ja das selbe nur 2 namen) 
verwende, das sollte auch ohne Hardware unterstützung gehen. Da war 
jedoch nur das problem wie ich die Daten in Binär codiere und dann 
einzelnd je tackt übertrage

von slow (Gast)


Lesenswert?

Dann mach dich doch mal schlau in Richtung I2C. Sollte doch kein problem 
sein. Oder?

von Coco J. (Gast)


Lesenswert?

Habe ich bereits,.. jedoch gibt es keine einheitliche codierung in binär 
für die datentypen.. ich kann damit ja alles übertragen was ich möchte.

sagen wir ich nehme ein wort, möchte diese übertragen, behalte im 
hinterkopf dass ich es z.b. als Zweierkomplement mit festkommastelle 
interpretiere

also : -5.1 im zweierkomplement (4 bit)

#define -5.1zweier 0xCD //0b11001101
#define TWI PORTA
#define 0 SDI
#define 1 SCLK
uint8_t counter;

senden:
if(flanke01(TWI, SCLK)==true) //flanke01(); ==true wenn flanke 0 auf 1
    {
        TWI |= (-5.1zweier & (0x80 >> counter) << SDI);
        //hier soll entsprechend abhöngig vom counter eine 1 oder 0
        //herauskommen
    }


auslesen:
//dann bräuchte ich die bitweise für jeden takt einen



if(flanke01(TWI, SCLK)==true) //flanke10(); ==true wenn flanke 1 auf 0
    {

        if((TWI & (1 << SDI))==1)   //hier soll geprüft werden ob eine
                                   //1 am SDI liegt
            {
                 PAKET |= 0x80 >> counter  //hier soll in abhängigkeit
                                          //vom counter das Paket an der
            }                             //richtigen stelle eine 1
                                          //gesetzt bekommen
        if(counter<8)
           {
               counter++;
           }else{
               counter=0;
           }

    }

bitte verzeiht syntaxfehler und weißt mich drauf hin.. ich bin sehr neu 
in der c programmierung. ich hoffe ich habe alles ausreichend 
kommentiert

von Sonstwer (Gast)


Lesenswert?

Wenn du wirklich nur zwei µC miteinander verbinden willst, ist I2C 
(aufgrund der zusätzlichen Addressierung) die schlechteste Variante der 
drei genannten Busse.

Wenn nur in eine Richtung gesendet wird, nimm SPI, wenn bidirektional, 
nimm UART.

von Coco J. (Gast)


Lesenswert?

ich will das ganze schonmal benutzten, da ich einen 
beschleunigungssensor habe der nur I2C versteht... da kann ich dann auch 
alles gleich in I2C machen.


Ist das was ich da geschrieben habe sinnvoll?

von Sonstwer (Gast)


Lesenswert?

Hast du zufällig den BMA020? Den kann man wahlweise mit I2C oder SPI 
ansteuern.


Falls ja: SPI ist schneller und einfacher zu programmieren (sowohl in 
Hardware als auch erst recht in Software).



Und noch ein Tipp: Beginne mit der C Programmierung auf dem Computer. 
Wenn du Strukturen, Enums, Zeiger und Zeiger auf Zeiger komplett 
verinnerlicht hast, ist das Programmieren eines µC total easy.


Und uns zu fragen ob du einen Syntaxfehler in deinem Code hast, kann 
nicht dein ernst sein. Drück doch einfach mal auf "Kompilieren" um es zu 
testen. Ich könnte mir aber vorstellen, dass er mit "#define -5.1zweier 
0xCD //0b11001101" Probleme hat.

von Coco J. (Gast)


Lesenswert?

ich fühl mich ziemlich dumm.. und es ist mir schon peinlich das zu 
fragen..

also ich habe mir jetzt was zusammengeschrieben aber es fehlt mir 
immernoch das glied wie ich die Daten von den Datentypen wie int8_t 
bitweise auslese..

am liebsten hätte ich die ausgabe als HEX oder soetwas.. dass ich dann 
per shift (der << befehl.. ich hoffe er heißt so) auslesen kann.

was ich etwas verstanden habe war der vorschlag vorhin mit "union"

also mit Union weise ich 2 "variablen" den selben speicherplatz zu. also 
teilen sie sich diesen speicherplatz und der speicherplatz des größeren 
datentyps ist der gesamtdatentyp...

also müsste ich ja

  union
  {
    unsigned bits;
    int8_t wert;
  } WERTE;

dann würde ich mit WERTE.wert = 8; in diesen speicherbereich die 8 
reinschreiben.


wenn ich dann also dann noch den struct befehl nutzte,.. da der ja mir 
die wahl lässt was ich mit meinem speicher tue...

     struct {
      unsigned b0:1;
      unsigned b1:1;
      unsigned b2:1;
      unsigned b3:1;
      unsigned b4:1;
      unsigned b5:1;
      unsigned b6:1;
      unsigned b7:1;
       } bits;

leider funktioniert das nicht so wie ich möchte.. könnte mir da wer 
unter die arme greifen?

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.